Skip to content
Back to themes

Theme schema reference

Mudlark themes are JSON documents. The theme builder covers the common case of picking colors and copying out a file. This page is the underlying schema, for anyone authoring themes by hand or extending what the builder produces.

Where themes live

Built-ins ship inside the app. User themes live in <vault>/.mudlark/themes/. Edits reload in the app when the file changes. A user theme whose id matches a built-in shadows it in the picker, taking the same display position with your colors. When you move the vault, the themes folder travels with your notes.

A minimal example

{

"id": "tide",

"displayName": "Tide",

"extends": "system-light",

"appearance": "light",

"tokens": {

"ink": "oklch(20% 0.02 250)",

"paper": "oklch(98% 0.01 90)",

"blue": "oklch(55% 0.18 240)"

},

"palette": {

"accent.primary": "{blue}",

"accent.warm": "oklch(72% 0.17 55)"

}

}

Each theme has a single appearance. To ship a coordinated light/dark pair, author two documents (for example tide-light extending system-light and tide-dark extending system-dark). The user pairs them in the picker's two slots under Follow System Appearance.

Top-level fields

FieldTypeRequiredNotes
idstringyesStable identifier. A user theme whose id matches a built-in shadows it.
displayNamestringyesThe name shown in the theme picker.
extendsstringfor user themesInherits from a built-in id and merges through the extends chain.
appearanceenumyeslight or dark. Each theme resolves to exactly one appearance.
colorSpaceenum-sRGB (default) or displayP3. Hex and OKLCH literals are interpreted in this space.
tokensobject-Named color literals you can reference from later fields with {tokenName}.
paletteobject-The 9-slot semantic palette (6 accents, 3 neutrals). See the palette slots table below.
editorobject-Colors painted on the editor surface. See the editor fields table below.
renderedobject-Colors for the rendered (right-pane) preview: background, text, secondary, tertiary, codeBlockBackground.
chromeobject-App-chrome colors: window background, scrollbar, link, find-highlight, completion success / failure, math error, delimiter, escape, heading.
mappingobject-Remaps ItemTypes (task, highlight, question, quotation, bullet, code, math, table, media, timer, comment, metadata) to palette slots. Most themes omit it.
codeobject-Maps highlight.js token classes (keyword, string, number, comment, type, function, etc.) to color expressions.

Editor block fields

Colors painted on the editor surface itself (the left pane). All values are color expressions.

FieldRequiredDefault when omitted
backgroundyes-
textyes-
cursoryes-
paperPatternyes-
gutterTextnotheme.metadata
activeLineBackgroundnotransparent (no wash)
focusOutlinenonone (outline suppressed)

The gutter background is not a themable slot. Every theme paints it transparent so the body paper-pattern reads as one continuous sheet across the editor pane and the line-number column. Older themes that still declare gutterBackground or gutterActiveBackground load without error. The values are discarded.

Palette slots

The palette is the semantic layer between concrete colors and content types. The nine built-in slots:

SlotConventionFallback
accent.primaryHeading color, "the brand color"-
accent.warmTasks, attention items-
accent.coolCode, math, structured content-
accent.altQuestions, alt accentaccent.primary
accent.supportMedia, supporting accentaccent.cool
accent.signalTimers, signal accentaccent.warm
neutral.strongStrong neutral (bullets)neutral.muted
neutral.annotationMid neutral (metadata)neutral.muted
neutral.mutedQuiet neutral (comments)-

You can also define custom slots: give them any dotted name (e.g. accent.tide.kelp) and reference them via slot:accent.tide.kelp.

Expression language

Every color field accepts a literal (#rrggbb or oklch(L C H)) or an expression that references named tokens ({name}), palette slots (slot:accent.warm), or system colors (system:controlAccentColor). Helper functions alpha, lighten, darken, mix, desaturate, and rotate are available for compositing.

Supported system: names

Semantic AppKit colors:

controlAccentColor, selectedTextBackgroundColor, linkColor, labelColor, secondaryLabelColor, tertiaryLabelColor, quaternaryLabelColor, textColor, textBackgroundColor, separatorColor, controlBackgroundColor, windowBackgroundColor

Named accent colors (auto-adapt to light / dark):

systemBlue, systemBrown, systemCyan, systemGray, systemGreen, systemIndigo, systemMint, systemOrange, systemPink, systemPurple, systemRed, systemTeal, systemYellow

A bare system:Name reference stays live: accent or appearance flips propagate automatically. Wrapping it in any function call collapses the value to a snapshot, refreshed only when macOS broadcasts a system-color change.