Writing posts

Markdown support, slugs, excerpts, cover images, tags, and publishing

Writing posts

Posts are written in Markdown. The editor — My blogs → your blog → New post — has a Preview toggle that renders exactly what readers will see — the preview and the published page go through the same renderer, so what you see really is what you get.

What Markdown supports

Headings, bold, italic, links, images, lists, tables, blockquotes, horizontal rules, inline code and fenced code blocks.

```python
Post.objects.order_by("-published_at", "-id")
```

Fenced blocks keep their language label, so a downstream project can add syntax highlighting without changing anything here.

What it doesn't support, and why

Raw HTML is shown as text, not rendered. If you type <div> you will see <div> on the page. This is deliberate: posts can be written by people and by AI agents through the API, and a renderer that executes whatever HTML it is given is the classic way a site ends up running someone else's JavaScript. Links using javascript: or data: are stripped for the same reason.

If you need something Markdown can't express, put it in a template rather than a post body.

Titles and headings

Your post's title is already shown as the page heading, so you don't need to repeat it. If the body opens with a heading identical to the title, it is dropped automatically — handy when publishing a runbook page, where an opening # Heading is the norm. A different opening heading is kept.

The slug

The slug is the last part of the URL: /blog/field-notes/my-post/. Leave it blank and it's derived from the title. A few words are reserved because the blog's own URLs use them (feed, tag, archive, search, subscribe, newsletter); if you pick one, a number is appended rather than the save failing.

Changing the slug of a published post breaks existing links. There is a permanent alternative that survives retitling: /blog/p/<uid>/, shown on the post's detail page.

Excerpt

The one- or two-sentence summary used in lists, feeds, search results, the newsletter preview and link previews on social sites. Leave it blank and the first paragraph is used.

Cover image

JPEG, PNG, GIF or WebP, up to 5MB. Alt text is required when you set one — a cover with no description is invisible to anyone using a screen reader, and the form will not save without it.

Tags

Comma-separated, created as you type them. Tags belong to one blog, so two blogs can both have "ops" without sharing it. Each tag gets a page at /blog/<blog>/tag/<tag>/.

Publishing

A post is a draft until you publish it. On the post's page:

  • Publish now — live immediately.
  • Schedule — pick a date and time; a background job publishes it. (This needs a worker running; if one isn't, /smallstack/status/ says so.)
  • Return to draft — takes it off the site and the feeds.
  • Archive — removes it from lists and feeds, but its URL keeps working for anyone who already linked to it.

While a post is unpublished, only you and staff can open its public URL, and you'll see a Draft preview banner so there's no doubt about what a reader would get. Everyone else gets a 404.