Frontmatter Is a Dead End (And Everything I Changed to Prove It)

By Jay Griffin, Claude Opus 4.6*Claude Opus 4.6 via GitHub Copilot·  March 2, 2026
🏷️ Tags:devcontent-systemsqliteprismp5jsworkflowretrospective

A marathon Copilot session that touched 70+ files, added relatedPosts everywhere — and the realization that this whole content system sorely needs a database.

relatedPosts Across Every Single Content File

I added relatedPosts metadata to every content file in the project — all 36+ markdown files and all 32+ TSX files. Each one mapped by topic, tags, and content relationships.

Then I tested it and nothing showed up on docs pages. Turns out RelatedPosts was only wired up in the /posts/[slug] route. The /docs/[slug] and /docs/commits/[slug] routes had no idea the component existed. Fixed all three routes, and while I was at it, made all of them look up both posts and docs so cross-type related links actually resolve.

What This Session Taught Me

Frontmatter Is Horrible

I have 70+ content files. Each one has a JSON frontmatter block that I have to hand-edit. There's no validation, no autocomplete, no referential integrity. When I added relatedPosts to every file, I was using slugs blindly and hoping they matched. A typo in a slug just silently fails — no related post shows up and nothing tells me why.

The ---json block format means my metadata lives in a weird no man's land: it's not a database, it's not TypeScript (so no type checking), and it's not even standard YAML frontmatter that tools expect. It's a string blob that gets parsed at build time. I just like JSON so it's what I use.

My docs/posts/commits Taxonomy Is Garbage

I have three content types (post, doc, doc:commit) served by three different route handlers that are almost identical but slightly different in annoying ways. The fact that I had to fix three separate page.tsx files to add RelatedPosts support is exactly the kind of duplication that shouldn't exist. The routing is doing too much work that should live in the data layer.

I Need SQLite

Every pain point from this session traces back to the same root cause: metadata is scattered across 70+ files with no centralized query layer. I want to:

This isn't a hypothetical anymore. I've been writing about migrating to SQLite for too long. This session was the final push — the content system works, but it works despite itself, not because of its design.

Related Posts

  • Why I'm Finally Moving to SQLite (And Why I Waited Until Now)
    After over 60 articles in one month, my file-based content system is breaking down. Here's why I'm migrating to SQLite, why now, and why I didn't do this sooner.
  • Vibecoding Plasma Cosmos from One-Prompt Toy to Real App
    A Claude skill generated a generative art app in one prompt. Then I spent an evening vibecoding it with Opus into something I actually want to keep.
  • CodeBlock Component Showcase
    Testing and showcasing all CodeBlock component configurations including bash/shell and markdown support
  • Content Architecture: TSX-First with markdown Fallback
    Why TSX is the first-class citizen and Markdown is just an input format