Skip to content
~/johan
← cd ..

Hello, world

· 1 min read · #meta

I've spent most of my career building and designing backend systems for banks, mostly for regulatory reporting. That work tends to stay behind the firewall, so this site is a place to write about the parts that can be shared: architecture, trade-offs, and lessons from making numbers add up.

How this site is built

A personal site is a small system, but it's still a system, so here's the architecture in brief:

  • Next.js 16 with the App Router and React Server Components. Every page is prerendered at build time.
  • MDX for posts. Each post is a file in the repo that exports its own metadata, and the build fails if that metadata is wrong.
  • Tailwind CSS v4 for styling, with light and dark themes set before first paint.
  • Vercel for hosting. A push to main deploys and every pull request gets a preview.

The metadata check is the same idea I'd use at work: validate at the boundary and fail loudly.

src/lib/posts.ts
function assertMetadata(slug: string, value: unknown): asserts value is PostMetadata {
  // ...
  if (problems.length) {
    throw new Error(`Invalid metadata in blog post "${slug}": ${problems.join(", ")}`);
  }
}

There's very little client-side JavaScript. Press Ctrl/⌘ + K to see most of it.

esc
↑↓ navigate · ↵ select · Ctrl K toggle