Themes
A theme is a site’s look packaged as one directory: templates, assets, and config defaults. Name one and your pages have a design.
theme "themes/albatros"
Pick one
Four ship with baudelaire, one per kind of site. Pick by what the site is. The look is the part you can change in an afternoon.
| Theme | For | Shape |
|---|---|---|
| albatros | A blog | A centered column. Bylines with avatars, lead images, tags, reading time, an opt-in contents list, related posts, light and dark, a language switcher on a site with editions. |
| spleen | A blog, no JavaScript | A terminal. Monospace throughout, a prompt for a masthead, posts as a directory listing, dark first. Not “minimal JS”: none. |
| phares | Documentation | A sidebar built from your own content/ tree, a search palette, the page’s headings down the right, breadcrumbs, an edit link, prev/next through the manual, and the components a manual writes with: callouts, tabs, steps, cards, badges. |
| paysage | A portfolio | A landing page, a work grid that builds itself from what you publish, one case study per project. |
Each name links a live demo.
All four ship a not-found.typ. Bind it from content/404.typ, which publishes as the flat 404.html a static host serves for an unmatched URL:
#let frontmatter = (title: "Not found", template: "not-found.typ")
Get one
All four are in the binary. Write one into the project:
baudelaire theme list # the four, one line each
baudelaire theme add albatros # writes themes/albatros/
Nothing is downloaded: the files land in your project and are yours from that moment, to read, edit, or replace.
A theme from anywhere else is the same command with a different spec:
baudelaire theme add ./elsewhere/plume # a directory on this machine
baudelaire theme add @preview/plume:1.0.0 # the Typst package store
baudelaire theme add gh:owner/plume#v1.2.0 # a forge repository, at a tag
baudelaire theme add https://x.dev/plume.tar.gz # an archive
A repository or an archive that holds a whole project takes --subdir, naming the directory the theme is in. Whichever it came from, the copy records where it came from, so
themes/plumeupdate goes back there. The CLI page has the whole table.
add leaves a small record beside them saying which files it wrote, which is what later lets baudelaire theme update <name> bring the untouched ones forward without walking over your edits:
baudelaire theme info albatros # what it ships, and what your copy has become
baudelaire theme update albatros # keeps every file you have changed
baudelaire theme remove albatros # and this keeps them too, unless --force
The CLI page has the whole table of what each verb does to a file you have edited, deleted, or added.
Adopt it
Name the directory it landed in:
theme "themes/albatros"
It has to sit inside the project root, because a Typst import can’t reach outside it. --dir puts it somewhere else inside the root; name that path instead.
Installed into your Typst package directory instead, a theme is named as a package and shared across every project on the machine:
cp -r themes/albatros ~/.local/share/typst/packages/local/albatros/0.1.0
theme "@local/albatros:0.1.0"
Only the preview namespace is ever downloaded. @local and any other namespace are read from disk and never hit the network.
Scaffolding a new site straight onto a theme writes only what a theme cannot decide for you: the site’s identity, its paths, and a preview. No templates, no assets, and no collections of its own, since a collections list of yours would replace the theme’s rather than add to it.
baudelaire init my-site --theme "themes/albatros"
A spec naming one of the four is written on the spot, so that one command is a project that builds:
◆ theme
➜ albatros 11 files to themes/albatros
A spec naming anything else is yours to put there, and the run says so rather than leaving the first build to find out.
--template is not used with --theme: what a starter shape would contribute is the part the theme already declares.
Then read the theme’s README for what it wants from a page. All four want a title; most use date, summary, and a taxonomy.
NOTE
A theme’stheme.kdl is a floor. Every key you state wins, nested blocks included, so adopting one never touches your site, url, or author.
WARN
Config lists replace wholesale. Declaringcontent { collections { .. } } of your own drops the theme’s set rather than adding to it. Copy the theme’s block first if you only meant to add a collection.
Change part of it
One rule: your file wins, file by file, across templates/, assets/ and static/. Everything else still comes from the theme.
| To change | Do |
|---|---|
| A layout | Copy templates/page.typ out of the theme into your own templates/ and edit it. |
| The look | Ship your own assets/style.css. It replaces the theme’s. |
| A color or a width | Copy the theme’s style.css and edit the custom properties at the top. Every theme here declares its whole palette there. |
/* assets/style.css, copied from the theme */
:root {
--measure: 48rem;
--accent: #7a3ea1;
}
Nothing else has to move. A theme you’ve overridden two files of is still a theme baudelaire theme update brings forward: the two files you changed are kept, the rest are rewritten.
Writing one of your own is a page of its own.