Writing posts on this site
Every markdown feature this blog supports, in one page — frontmatter, code blocks, callouts, tables and footnotes.
Posts live in content/posts/ as .mdx files. Drop a file in, and it shows up
on the blog — no registry to update, no route to add. This post is the cheat
sheet; keep it around or delete it once you know the shape.
Frontmatter
Every post starts with a YAML block:
---
title: "Escaping a hardened container" # required
description: "One-line summary for cards, meta tags and RSS."
date: 2026-09-08 # required, YYYY-MM-DD
updated: 2026-09-12 # optional
tags: ["linux", "containers"] # optional
draft: true # optional, defaults to false
slug: "custom-url-slug" # optional, defaults to filename
---Only title and date are required — a missing one fails the build loudly
rather than shipping a broken post.
draft: true keeps a post visible on npm run dev and out of every
production build. Flip it to false when you are ready to ship.
Starting a post
npm run new -- "Escaping a hardened container" --tags linux,containersThat writes content/posts/escaping-a-hardened-container.mdx with the
frontmatter filled in and draft: true already set.
Code
Fenced blocks are highlighted at build time with Shiki, so there is no highlighter shipped to the browser. Hover a block to copy it.
from pwn import *
def build_chain(base):
pop_rdi = base + 0x2a3e5
ret = base + 0x2a3e6
return flat(ret, pop_rdi, base + 0x1d8678, base + 0x50d60)Three things worth knowing:
title="rop.py"adds the filename bar.showLineNumbersdoes what it says;showLineNumbers{7}starts at 7.{4-5}highlights lines, and/needle/highlights matching words.
Inline code like mmap(2) needs nothing special.
Callouts
<Callout type="warning" title="Careful">
Body text, with **markdown** inside.
</Callout>Tables
GitHub-flavoured markdown is on, so tables, task lists, strikethrough and autolinks all work.
| Primitive | Where it lives | Notes |
|---|---|---|
getAllPosts | src/lib/posts.ts | Reads and caches the directory |
mdxOptions | src/lib/mdx.ts | remark/rehype plugin chain |
siteConfig | src/lib/site.ts | Name, URL, nav, socials |
- Task lists render
- Even unchecked ones
Everything else
Blockquotes pick up a brand-coloured rule.
Footnotes work too1. So do headings down to ####, ordered and nested
lists, horizontal rules, and images:
Anything in public/ is served from / — put screenshots in
public/images/.
Styling knobs
The whole palette is CSS variables in src/app/globals.css. The one
non-shadcn token is --brand, the accent used for links, active states and
the terminal glyph in the header — change its hue and the site re-skins.
Article typography is the .prose block in the same file.
Footnotes
-
Like this one, collected at the bottom of the page. ↩