Welcome — a tour of the writing system

A living style guide. Every component, plugin, and authoring trick the new site supports lives here.

5 min read
Save Ferris cover image
Table of contents
  1. Headings, paragraphs, and inline marks
  2. Callouts
  3. Code blocks
  4. Figures and images
  5. Video
  6. Diagrams (D2)
  7. Math
  8. Charts
  9. Tables, lists, footnotes
  10. Asides
  11. A horizontal rule
  12. What this is, and isn’t
  13. Footnotes

Welcome. This post is a living style guide for the new site. It exercises every component, plugin, and authoring affordance the site supports, so I have a single place to remind myself how to write the next post.

Headings, paragraphs, and inline marks

Each heading on this page has an autogenerated id and an anchor link that appears on hover. Text supports the usual marks: strong, emphasis, inline code, strikethrough, and external links.

Block quotes look like this. They’re sized down a touch and use a left rule in the brand neutral.

— Someone wise

Callouts

Code blocks

Powered by Expressive Code. Plain fenced blocks get language-aware highlighting, copy buttons, and theme-aware colors that follow the site’s light/dark mode automatically.

src/lib/posts.ts
import { getCollection, type CollectionEntry } from "astro:content";
export type Post = CollectionEntry<"blog">;
export async function getVisiblePosts(): Promise<Post[]> {
const all = await getCollection("blog", ({ data }) => !data.draft);
return all.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
}

You can mark a single line, ranges, and add inline annotations:

function add(a: number, b: number): number {
const sum = a + b; // this line is highlighted
// these next two are inserts
if (sum > 100) {
console.warn("big sum");
}
return a + b; // this line is a delete
return sum;
}

A terminal frame:

setup
npm install
npm run dev

A diff block:

const post = await import(`../../../lib/blog-posts/${params.slug}.md`);
const post = await getEntry("blog", params.slug);

Inline code: write await getCollection("blog") to fetch every post.

Figures and images

Markdown images work as you’d expect:

A built-in markdown image, optimized by Astro

For more control use <Figure>:

A figure with a caption
Caption text appears below the image. The image itself is responsively optimized.

Video

For self-hosted video, use <Video>. It supports posters, autoplay, captions, and a default fallback. Below is a placeholder to show the layout.

For YouTube embeds, the lite-loader from astro-embed keeps the page light until the user clicks play:

Play

Diagrams (D2)

Fenced blocks tagged d2 render to inline SVG at build time via the D2 WebAssembly engine. Zero client JS, zero round trips, no headless browser needed.

Author writes MDXZod schema validates frontmatterremark + rehype + Expressive CodeBlogPostLayout renders ContentStatic HTML + a few hydrated islands

Sequence diagrams work too:

UserBrowserService Worker Click /blogGET /blogCached HTMLRender

Math

Inline math via $...$: the area of a circle is A=πr2A = \pi r^2. Block math via $$...$$:

i=1ni=n(n+1)2\sum_{i=1}^{n} i = \frac{n(n+1)}{2}

Charts

<Chart> is a Svelte island. It hydrates only when scrolled into view, so the rest of the page ships zero JS for charts.

A made-up time series

0102030405012345678910ValueDay

Tables, lists, footnotes

ToolRoleBundle impact
AstroStatic site generatorBuild-time only
SvelteInteractive islandsPer-island
Expressive CodeCode highlightingBuild-time only
PagefindStatic full-text searchLoaded on /search

Ordered list:

  1. Draft the idea.
  2. Sketch the structure.
  3. Write the first pass without editing.
  4. Edit ruthlessly.

Unordered list:

  • Keep paragraphs short.
  • Lead with the conclusion.
  • Use callouts sparingly.
  • Show, then tell.

Task list:

  • Pick a stack
  • Build the design system
  • Write more posts
  • Ship it

A footnote example.1

Asides

A horizontal rule


What this is, and isn’t

This page is the source of truth for the writing system. When something stops working, fix it here first — if the welcome page is happy, every other post will be too.

Footnotes

  1. Footnotes show up at the bottom of the post and link back to where they were referenced.