I turned my portfolio design into a template. The code was done. The real work was removing myself from it.

This post is about the unglamorous parts of packaging software for other people: what had to change, what I almost forgot, and what's still unfinished. If you're thinking about selling a starter kit or template, this is the checklist I wish I'd had.

Why a template

As I wrote on Day 4, I weighed several ways to earn online and chose the one that needed the least new work: packaging a design system I'd already built. A portfolio template is something other students genuinely need, and it was a better fit than starting a product from scratch.

The principle: separate the owner from the engine

My live site is full of me: my name, links, location, project list, certificates, even phrases in the chat assistant's persona. A template can't have any of that hard-coded. Everything owner-specific has to live in one clearly marked place, and the rest has to read from it.

I worked on a separate copy, so the live site stayed untouched. (That's the "copy, don't rewrite" approach from Day 22.)

What had to change

1. One config file for every owner-specific fact

All the personal facts moved into a single site object: name, tagline, links, location, and values derived from them (full name, site URL, and so on).

// src/data/site.ts (simplified) export const site = { name: 'Avery Quill', tagline: 'Designer-developer', url: 'https://your-site.example', location: 'City, Country', github: 'https://github.com/your-username', }; export const FULL_NAME = site.name; export const SITE_URL = site.url; 

Then I hunted for hard-coded copies. This is the tedious part: search for the old name, old URLs and old city across HTML, scripts, metadata and generated files. Every miss would have shipped a stranger's details to a buyer.

2. A template-driven index.html

The HTML head contains the title, description and social tags, which must also come from the config. A small build plugin fills the HTML from the same data, so the page's metadata can't disagree with the site.

3. Build scripts that read the same config

Anything that runs at build time (sitemaps, feeds, prerender, share images) had to read from the config too, through one loader, instead of having their own copies of the facts.

4. A section list that controls the page

A sections array decides which home sections render and in what order. A buyer who doesn't want a blog section removes one line.

5. Parameterised APIs

Some small stats endpoints took a hard-coded username. They now accept a query parameter, so a buyer's data shows up instead of mine.

6. The assistant persona

The chat assistant's knowledge and persona are generated from an OWNER object, so a buyer gets an assistant that talks about them.

A sample persona, not my life

The template ships with a fictional owner ("Avery Quill", The Quill Review) and placeholder links (your-username, your-site.example). Sample PDFs and images are generated by a script, so no personal photos or real certificates are included.

The licence question

This one almost slipped past. The live site has a little pixel mascot. I wasn't certain I could legally redistribute those sprites, so I removed them from the template and made a mascot an optional config feature instead.

The rule I took: if I can't verify the licence of an asset, it doesn't ship. Fonts, images, icons, sounds, sprites. Check each one. Selling something that includes someone else's work without permission is a serious problem, and "I found it online" isn't a licence.

I also wrote a draft licence for the template itself. It's a draft, not legal advice, and anyone selling software should get proper advice for their situation.

Test like a buyer

The most valuable check: do what a buyer will do, from scratch.

unzip press-template.zip -d /tmp/buyer-test cd /tmp/buyer-test/press-template npm ci npm run typecheck npm run build 

Do it in a clean directory, not your working copy. Things that work on your machine because of leftover files or cached installs will fail here. I also made a customised copy (changing the name, links and sections) to confirm that the config really controls everything.

What I found along the way

Packaging forced me to look at the code with fresh eyes, and I found real bugs in the live portfolio:

  • The command palette ignored the Escape key.
  • A certificate modal's animated children lacked React keys.
  • Certificates without a URL crashed the modal and the featured row.

All three were fixed in the live site too. Preparing something for strangers is a great forcing function for quality.

What I haven't finished

The honest status, as on Day 4: the template is built and verified, the listing copy and screenshots are ready, and a demo is deployed. But the Gumroad listing is a draft that's not published, because payouts need bank details I haven't connected.

So: built, tested, not shipped. Naming that publicly is partly to make it harder to leave it that way.

A checklist you can reuse

  • [ ] Every personal fact lives in one config file
  • [ ] Search for your name, handles, URLs, city across all files
  • [ ] Sample content uses a fictional persona
  • [ ] No personal images, documents or certificates
  • [ ] Every asset's licence is verified, or the asset is removed
  • [ ] A README with setup steps a stranger can follow
  • [ ] A clean install and build from the final zip
  • [ ] A customised copy to prove the config works
  • [ ] A licence file (get advice)
  • [ ] Listing text that says exactly what's included, and what isn't

Lesson

"It works for me" and "someone else can use it" are different levels of finished. The second one took longer than the first.

Writing the listing page

A template listing has to answer a buyer's questions fast. Mine follows this outline:

# Name: one-line promise ## What you get - A complete React + TypeScript site (list the main sections) - Design system with tokens and primitives - Sample content you can replace - Documentation: setup, customising, deploying ## Who it's for / not for For: students and developers who want a distinctive portfolio. Not for: people who want a no-code builder. ## Requirements Node version, package manager, hosting suggestions. ## What's *not* included Domain, hosting, your content, support beyond [stated scope]. ## Preview Screenshots, a live demo link. ## Licence Plain-language summary + link to the full text. ## Changelog Version history. 

The "what's not included" section prevents refunds and disappointment.

README for the buyer

The README should get a stranger from zip to running site:

  1. Requirements.
  2. Install and run commands.
  3. Where to put your information (the one config file).
  4. How to add a project, a post and a certificate.
  5. How to change colours and fonts (the tokens).
  6. How to deploy.
  7. Troubleshooting for the three most common problems.
  8. Licence and credits.

A README that a first-time buyer can follow without asking you anything is a product feature.

Support and refunds: think before you sell

I'm not a lawyer and rules differ by country and platform, so treat this as a prompt, not advice:

  • Decide in advance what support you'll offer (for example, installation questions for 30 days) and say it plainly.
  • Read the platform's terms about refunds, taxes and payouts.
  • Check whether you need to register for tax in your country once you earn.
  • Keep a record of what you sold, to whom and when.

Handling this before the first sale is much less stressful than after.

A pre-launch dry run

Do this on a machine that has never seen your project:

  1. Download the zip from the listing, as a buyer would.
  2. Follow the README to the letter. Note every place you hesitate.
  3. Change the name, links and colours. Does everything update?
  4. Build and deploy somewhere.
  5. Fix what confused you, then repeat with a friend.

Every point of friction you fix is a support email you won't answer later.

Versioning and updates

If people buy it, it needs maintenance. A lightweight plan:

  • Semantic version numbers (1.0.0, 1.0.1…).
  • A changelog.
  • A promise about how long you'll support a major version.
  • A note on dependencies: they age, and security updates matter.

Be honest about what you can maintain. An abandoned template with promises is worse than a small one that's kept updated.

What I'd tell my past self

  1. Set up payouts on day one, not last.
  2. Write the README before the last feature.
  3. Check licences as you add each asset, not at the end.
  4. Test from a clean zip early. Many problems only show there.
  5. Price low, and treat it as an experiment you learn from.

Key takeaways from day 27

If you've sold a template or starter kit, what surprised you most?

☕ Enjoyed this post? You can support my writing on Ko-fi.

Support me on Ko-fi