DEV Community

AIVCJ studio
AIVCJ studio

Posted on Originally published at portfolio.aivcj.com

What broke when we set up our own templates as a buyer

Most of it worked. All 15 zips installed and built on a clean machine. But we found three packages that were far bigger than they should have been, missing setup docs, a licence file that named the wrong licences, and five bugs a buyer would have hit on their first day. This is the list, with the fixes.

We sell themes and kits on Pulse. Until last week we tested each one as its builder: in the project folder, with our own tools around it. A buyer gets something else. They get a zip, a fresh machine and a README. So we stopped testing the project and started testing the zip.

How we tested

We wrote one script that does what a buyer does, in order, for every product in the store:

  1. Unzip the download into an empty folder.
  2. npm ci, then a type check.
  3. npm run dev and open the home page.
  4. npm run build, then npm start.
  5. Open up to 10 pages at 360, 768, 1280 and 1536 pixels wide, with reduced motion on.
  6. Compare every page with the hosted demo the buyer saw before paying.

It ran on two Node versions, 24.22 and 22.23, because buyers don't all update at the same time. That came to 348 page checks, each compared with the live demo. We also loaded the pages again with the clock set a year ahead, which found a bug we would never have seen.

What was wrong with the zips

Build folders in the download. Three zips carried our local build output (.next-check and .next-dev). Sorted was 77.2 MB. After the fix it is 1.2 MB. Maun went from 22.9 MB to 7.0 MB. A buyer would have downloaded tens of megabytes of files that were useless to them.

Our own files. Some zips had our internal check scripts, a .forge.json, TypeScript build caches and a package name of dp-theme. None of that is harmful, but it is noise, and it tells a buyer nobody looked inside the zip.

The wrong README. Three products shipped our starter kit's README instead of their own. A buyer opening the folder would read about a different project.

No licence file, or the wrong one. Most zips had no licence file. AURORA had one, but it said "Single" and "Unlimited". Pulse sells Personal and Commercial licences, so the zip and the store disagreed.

The fix was one packaging script that every product now goes through. It copies only what the buyer needs, writes the product's own README, adds the Pulse LICENSE.txt, adds .env.example when the code reads environment variables, checks the lockfile matches package.json, and sets engines to Node 20.9 or newer, so npm warns a buyer whose Node is too old.

Five bugs a buyer would have hit

1. A page that scrolled sideways on phones. Lunetta's cabins page moved 250 px to the right at 360 px wide. The table had its own scroll area, but the hidden labels for screen readers sat outside it and stretched the page. The hosted demo had the same bug. We moved the labels inside the scroll area.

2. and 3. Two smaller sideways scrolls. Peel's home page by 8 px (a flag on the map) and Sorted's pricing row by 3 px. Small, but on a phone it feels like the page is loose.

4. A chart label that broke hydration. AURORA's dashboard showed React error #418. The server drew a chart axis label as $0 and the browser drew $0.0. Both are fine on their own. When they differ, React throws away the server HTML and redraws the page. The label went through a compact number format, and Node and the browser did not agree on it. We now pick one explicit format per axis, with fixed decimals, so both sides print the same text.

5. Dates frozen at build time. This is the one the year-ahead load found, in three products. The swatch-test theme shows delivery dates, and the two résumé themes show "this year". Those were written into the HTML when the site was built. Open the site on a later day and the browser computes a different date than the HTML says, and React throws #418 again. A buyer who built the site once and visited it next month would have seen it. We now compute those dates in the browser after the page loads.

A setup step in the new Documentation guide, with the command to run and what you should see

Setup docs in every zip

Each download now has a Documentation/index.html that works offline. It walks through six steps, from unzip to a live site, with diagrams of what happens at each step, real screenshots of the product, a tour of the pages, fixes for the problems people usually hit, credits for fonts and images, and how to reach us. It reads well on a phone too.

We checked the guide the same way as the products: 15 guides at 4 widths in light and dark mode, 120 checks, nothing failing.

The numbers after the fixes

Before After
Largest zip 77.2 MB (Sorted) 25.2 MB (Lunetta)
Zips with our build folders inside 3 0
Zips with the product's own README, Pulse licence and setup guide none had all three 15 of 15
Products with a bug a buyer would hit 7 0 (plus 1 one-off we could not repeat)

Second round: 14 of 15 products had zero snags. Playable Résumé showed one #418 once on its home page at 360 px, and not again in 31 tries. We are still watching it.

What we'd tell anyone selling templates

Test the download, not the project. Your project folder has things the buyer's never will, and it hides exactly the bugs they hit first. Set the clock forward a year at least once. And read your own README as if you had never seen the code.

Every Pulse download, including AURORA and Lunetta, is now built by this packaging script. If something still doesn't work as described, write to us and we fix it.


First published on Pulse by AIVCJ.

Top comments (0)