Sep 10, 2026 · 1 min
Type-safe content belongs in a portfolio
- typescript
- content
- nextjs
A personal site is a content problem dressed as a design problem. The temptation is to hand-write a few cards and move on. That works until the third post is missing a date.
I parse MDX with gray-matter and validate it with Zod. The loaders return a typed BlogPost or Project. Pages never see raw frontmatter. Invalid files fail next build.
That is not ceremony. It is the same instinct you want in a production app: make illegal states unrepresentable, then generate the routes from what remains.
The reading time is derived. Drafts are a boolean, not a separate folder you forget to exclude. Tags are a union of what the files actually use.
None of this requires a CMS. Git is the CMS. The schema is the contract.