back to all posts

Why this site left Next.js for SvelteKit

Rebuild notes. Moving nhg.design from Next.js to a fully static SvelteKit site, and why less machinery is the feature.

The previous version of this site ran on Next.js. It worked. It also shipped a React runtime, a server I had to think about, and a dependency tree that wanted attention every few months, all in service of what is honestly a brochure with a blog. The rebuild is SvelteKit compiled to plain static files, and the difference is not subtle.

the mismatch

Next.js earns its complexity when you use what it is for: per-request rendering, middleware, image pipelines, incremental regeneration. A studio site uses none of that. Every page here is knowable at build time. Paying for request-time infrastructure to serve build-time content is the mismatch, and I had been paying it for years, mostly in upgrade churn between app router revisions and the periodic “your build is deprecated” email.

The test I now apply to any small site: if you can name every URL before deploying, you want static files. This site passes trivially.

what the new stack is

SvelteKit 2 with adapter-static and prerender = true at the root. The build walks every route and writes HTML. The output deploys to Cloudflare Pages, which means the hosting bill is zero, there is no server to patch, and the site is on the edge without me configuring anything.

Svelte compiles components away instead of shipping a framework to interpret them, so the JavaScript that does reach the browser is small and specific: the theme draw, the generative canvases, the reveal observer. A visitor with JavaScript disabled gets the entire site in fallback colors.

Posts are mdsvex files: markdown with frontmatter that can import real Svelte components inline. The interactive color demo in the studio post is a component sitting in the middle of the markdown, prerendered with the rest of the page. No embed, no iframe.

longevity is the point

Performance was the advertised reason and it delivered: no server round-trips, HTML at the edge, nothing blocking first paint but a font. But the argument that actually moved me is duller. The build output is a folder of files. Files do not have CVEs. A folder of HTML from 2010 still serves today; a Next.js 12 app from the same era needs an archaeologist.

For client work this matters more than for my own site. A small business does not want a maintenance contract as a structural requirement of owning a website. When the site is static, the worst-case future is that it keeps working exactly as deployed. That is a strange sentence to write about web technology, and it seals the argument for me.

The trade-offs are real: no request-time personalisation, forms need an external endpoint, and the visit-random theming had to move client-side, which is why an inline script draws the colors before first paint. Every one of those was solvable in an afternoon. The problems I deleted used to be permanent.