How posts work
2 min read
Contents
Posts live in src/content/blog/ as .md or .mdx files. The file name becomes the URL, so
writing-a-post.mdx is served at /blog/writing-a-post.
Frontmatter
Every post is validated against a Zod schema at build time. A typo in a field name fails the build instead of silently producing a broken page.
| Field | Required | Notes |
|---|---|---|
title |
yes | Up to 120 characters |
description |
yes | Used in listings, <meta> tags and the RSS feed |
pubDate |
yes | YYYY-MM-DD |
updatedDate |
no | Set when revising a published post |
draft |
no | Hidden in production, visible in astro dev |
tags |
no | Free-form; tag pages are generated from what’s used |
slug |
no | Overrides the URL derived from the file name |
featured |
no | Pins the post to the top of the home page |
Markdown or MDX
Plain .md covers almost everything: headings, lists, tables, footnotes, and syntax-highlighted
code blocks all work without any extra syntax.
Reach for .mdx when a post needs something Markdown cannot express — an interactive chart, a
diagram component, a live example. MDX lets you import a component and drop it into the prose:
import Chart from '@/components/react/Chart';
<Chart client:visible data={results} />
That client:visible directive is the important part. The component renders to static HTML at build
time and only hydrates when it scrolls into view, so a post with one interactive widget does not pay
for JavaScript on every other post.
Drafts
Set draft: true while a post is in progress. It shows up in astro dev — with a “Draft” label and
a noindex tag — and disappears from production builds, the sitemap and the RSS feed. Flip it to
false when the post is ready.