Skip to content

2026-07-04 · 1 min read

Rebuilding 1zero9.com in the open

Why I deleted my own website, kept only the logo, and what the first day of the rebuild taught me about motion and Largest Contentful Paint.

This site used to be a studio website — service tiers, a portfolio grid, a site-builder wizard, even an AI holiday concierge living under the same roof. All of it worked. None of it said what I actually wanted to say.

So I deleted it. One git tag preserves the whole era (archive/pre-rebuild-2026-07); the only survivor is the logo — a single continuous line that draws "109" as a waveform. That line became the brief for everything else: signal over noise.

The stack

Next.js 16, React 19, Tailwind CSS 4, and MDX compiled through content-collections with Zod-validated frontmatter. Adding a project is one folder and one file; getting the frontmatter wrong fails the build, which is exactly the kind of error you want at authoring time instead of in production:

const projects = defineCollection({
  name: "projects",
  directory: "content/projects",
  include: "*/index.mdx",
  schema: z.object({
    title: z.string().min(1).max(80),
    summary: z.string().min(1).max(200),
    date: isoDate,
    status: z.enum(["featured", "active", "archived"]),
  }),
});

The lesson of day one

The first Lighthouse run came back at 91 — because I'd done the obvious thing and wrapped entrance animations in a client-side motion library. Server-rendered HTML arrived with opacity: 0 inlined, and the largest content block stayed invisible until React hydrated. LCP: 3.4 seconds, for an effect that lasts half a second.

The fix was to make the animations CSS keyframes instead. They start at first paint, need no JavaScript at all, and prefers-reduced-motion collapses them via one global rule. LCP dropped to 2.6 seconds on a throttled mobile lab run, and the only client JavaScript left on the page is the theme toggle.

Restraint, it turns out, is also a performance strategy.