docs

~/docs/content

Writing content

How to add posts, projects, docs, and standalone pages with typed frontmatter.

on this page

All content lives in src/content/. Each folder is a collection with a schema in src/content.config.ts; a typo in frontmatter fails the build with a clear message instead of silently rendering wrong. Files whose name starts with _ are ignored everywhere.

Posts

Create src/content/posts/my-post.md (or .mdx). Sub-folders are allowed — the file path becomes the URL, so posts/gpus-on-kubernetes/part-1.md is served at /posts/gpus-on-kubernetes/part-1.

src/content/posts/my-post.md
---
title: 'My post'
description: 'One or two sentences for the list, RSS, and social cards.'
date: 2026-07-20
updated: 2026-07-25 # optional
tags: ['kubernetes', 'gpu']
series: 'GPUs on Kubernetes' # optional — enables "in this series"
image: '/images/posts/cover.png' # optional — cover + Open Graph image
externalLink: 'https://…' # optional — link the title elsewhere
draft: false
---
Your content here.
  • series groups posts: every post with the same series name gets a numbered “in this series” block, in reading order.
  • externalLink turns the post into a link-out (no page is generated) — handy for talks and guest posts.
  • Drafts render in npm run dev but are skipped by npm run build.

Images with captions

An image on its own line with alt text becomes a <figure> with a caption:

![The caption goes here](/images/posts/diagram.svg)

Every Markdown image is lazy-loaded. External links open in a new tab with rel="noopener noreferrer".

Code blocks

Fenced blocks are rendered by Expressive Code. Useful meta on the opening fence:

Fence meta Effect
yaml title="deployment.yaml" {3-4} editor frame with a file name, lines 3–4 highlighted
bash frame="terminal" terminal frame
go showLineNumbers line numbers
yaml ins={4} del={3} green / red diff markers

Code blocks stay dark in every scene, light ones included — see Scenes & colours to change that.

Projects

src/content/projects/rollout-sentinel.md
---
title: 'Rollout Sentinel'
description: 'What it is, in one sentence.'
image: '/images/projects/rollout-sentinel.svg' # or .png / .webp / .webm / .mp4
skills: ['Go', 'Kubernetes', 'Prometheus']
link: 'https://github.com/…' # where the title goes
sourceCode: 'https://github.com/…' # optional separate repo link
order: 1
featured: true
---

A project with no body is a row/card that links out. A project with body content also gets its own page at /projects/<id>, and the title links there instead (the outbound link becomes a “view project” link on the card). link may be an internal path such as /tags/gpu if the “project” is a series of posts. Videos (.webm, .mp4) autoplay muted and looped.

Docs

src/content/docs/guides/my-guide.md
---
title: 'My guide'
description: 'Shown in the docs index and as the page subtitle.'
group: 'Guides' # sidebar heading
order: 10 # position within the group
---

Groups appear in the order their first page is encountered (by order), so give your “Getting Started” pages the lowest numbers.

Pages

Any file in src/content/pages/ becomes a top-level route: about.md → /about, uses.md → /uses. The page shows a ~/about kicker, the title, and the description as a lede.

src/content/pages/about.md
---
title: 'About'
description: 'Optional lede under the title.'
noindex: false
---

MDX components

In .mdx files the <Callout> and <Tabs> components are available without imports — see Component reference. The post Writing with MDX shows every feature on one page.