Skip to content
chornous.dev

Type two or more letters. Esc closes.

Index of sheets
Theme

Sheet 03 · Writing

All notes

From JAMstack to the App Router

A static site can carry search, feeds and interaction without turning into a backend project. The hard part is the contracts between those systems.

Pl. 29 · pipeline drawing generated from the slug “from-jamstack-to-app-router”

The JAMstack pitch fit on a slide: prebuild the pages, put them near the reader, and skip the servers you don't need.

The pitch still holds. The sites changed around it. A portfolio or a docs hub now wants typed content, local search, an RSS feed, per-route metadata and some interaction, and you can have all of that without running a backend.

Static pages can still move

Separate runtime data from runtime interaction. A blog post needs no server request to render. A search dialog or a draggable card can hydrate on its own and leave the rest of the page as plain HTML.

The App Router split I use for content sites:

  • Server components render content and metadata.
  • MDX files keep the writing editable in Git.
  • Zod validates frontmatter before anything publishes.
  • Pagefind indexes the prerendered HTML.
  • Client components own the interaction layer and nothing else.

Where migrations break

Migrations break at the contracts between systems, so check those first:

  • Draft filtering has to match across the blog, tags, RSS, sitemap and search.
  • Dynamic routes need deterministic static params.
  • Images should come from public paths, not a framework-specific pipeline you'll have to unpick later.
  • Animations have to respect reduced motion and leave the layout alone.

Settle those early and the rest of the move is typing.

What I optimize for

I want a static site that is easy to publish, easy to inspect, and hard to break by accident. Typed content goes in, predictable pages come out, and the interaction code stays isolated enough that an ambitious visual layer can't slow the whole page down.

Volodymyr Chornous