sammys.ai
← All posts

How this site is built

2 min readmetaweb

This site is a static Next.js app styled with Tailwind, with posts written in MDX. Here's a quick tour of the decisions, mostly so future-me remembers why.

The stack

LayerChoiceWhy
FrameworkNext.js (static export)App Router, one mental model for pages and games
StylingTailwind CSS v4Design tokens as CSS variables, dark mode for free
ContentMDX + gray-matterPosts are files in a folder, no CMS to babysit
HostingCloudflareStatic assets at the edge, effectively free

Posts are just files

Every post is an .mdx file with a small frontmatter block:

content/blog/hello-world.mdx
---
title: "Hello, world"
date: "2026-08-04"
description: "The obligatory first post."
tags: ["meta"]
---
 
Every site needs a first post, and this is it.

At build time a small helper reads the folder, parses frontmatter, and computes reading time:

lib/blog.ts
export function getAllPosts(): Post[] {
  return fs
    .readdirSync(BLOG_DIR)
    .filter((f) => /\.mdx?$/.test(f))
    .map(parsePost)
    .sort((a, b) => (a.date < b.date ? 1 : -1));
}

No database, no admin panel. Publishing is git push.

The design system

The look borrows from editorial print more than from tech landing pages: a warm cream canvas, warm near-black ink, one ember accent, hairline borders, and display type with tight negative tracking. Every color lives in a CSS variable, so dark mode is a single class flip on <html> — the games even read the variables at draw time, so the Snake board re-inks itself when you toggle themes.

What I'd tell you to steal

  1. Static export. If your site can be static, make it static.
  2. Tokens first. Get the palette into variables before styling anything.
  3. Click-to-play embeds. Video pages load no third-party JS until a visitor actually presses play.