Skip to content

Hello, world

A sample post showing the frontmatter contract the blog loader expects.

TownReels
2 min read
On this page3 sections

This post exists to demonstrate the frontmatter contract. Delete it once you have a real post — python tools/new_post.py --title "..." scaffolds one with the same fields already filled in.

The frontmatter contract#

Every field above is read by web/src/lib/blog.ts:

  • title — the <h1>, the <title> tag, and the generated social card.
  • slug — the URL segment. Lowercase ASCII and hyphens only; it must match the filename, and the backend's view-count endpoint rejects anything else so junk cannot enter the table.
  • description — the meta description and the card subtitle. One sentence.
  • date — YYYY-MM-DD. Also the scheduling mechanism; see below.
  • tags — a YAML list. Each tag gets its own indexable page at /blog/tags/<tag>, and those pages are in the sitemap.
  • author — shown in the byline and used as the JSON-LD author.
  • draft — true hides the post from production builds entirely.

Scheduling a post#

A post is published by being rebuilt on the right day, not by an external CMS. The loader excludes any post whose date is in the future from production builds, while next dev shows everything so you can preview what is queued.

So the workflow is: commit the post with a future date and draft: false, and it sits in the repository, absent from the built site. On the morning its date arrives, a rebuild reveals it. .github/workflows/blog-reveal.yml is that rebuild — a weekly cron that checks whether any post is due today, and if so triggers a deploy, purges the CDN cache, and submits the sitemap to IndexNow.

If no post is due, the workflow exits without deploying. Once the queue drains, the cron is a no-op.

Writing#

Markdown is rendered by marked at build time. Headings at depth 2 and 3 get anchor ids and feed the table of contents automatically.

Content is repo-committed and therefore trusted, so the rendered HTML is deliberately not sanitized — which also means you should not paste untrusted markdown into content/blog/.

Get started

Try it yourself

Replace this copy with a description of what a reader gets by signing up. Keep it descriptive — say what the product does, not what the reader should do.

Written by

TownReels

TownReels — Videos of your food, ready to post.