Custom themes

Recolor the Jotura desktop app with one JSON file in your vault: turning it on, every token it accepts, contrast targets, ten starter palettes, and what happens when the file breaks.

A custom theme is one file in your vault, Jotura/theme.json. Turn on Custom theme under Settings, Appearance, and Jotura writes that file with the palette of the built-in theme you have selected. Change any color in it, save, and the app repaints as soon as the file lands on disk.

The file is an ordinary vault file, so it syncs to your other computers with your notes, and any text editor or the jotura CLI can change it. Themes set colors only. Fonts have their own settings, and there is no custom CSS. Themes apply to the desktop app. The Android app keeps its own appearance.

Turning it on

  1. Open Settings and find the Appearance section.
  2. Pick the built-in Theme you want to start from. Its colors become the seed for your file.
  3. Switch on Custom theme.

Jotura creates a Jotura folder at the root of the vault, if there is not one already, and writes Jotura/theme.json. The seeded file is named after its base, such as Graphite (custom), and holds that theme’s ten core colors for both light and dark. Some built-ins seed a few extra tokens as well.

If Jotura/theme.json already exists, because it synced from another computer or you wrote it yourself, Jotura uses it as it is and writes nothing.

An Open theme file button appears under the switch and opens the file in a tab. The Theme row then shows an extra card carrying your file’s name and the label on <base theme>. Picking a different built-in card while the custom theme is on changes the base your file layers over.

What is stored where

Theme and Custom theme are vault settings, stored as themeName and customThemeEnabled in Jotura/settings.json. Every computer that opens the vault gets the same look. Mode (System, Light, or Dark) stays on each device, so one computer can follow the operating system while another stays dark. With Mode on System, Jotura follows the operating system as it switches.

The file format

The file is a JSON object with an optional name and two optional palettes, light and dark. At least one palette is required. Jotura uses the palette that matches the current mode.

{
  "name": "Harbor",
  "light": {
    "accent": "oklch(48% 0.14 200)",
    "accent-contrast": "#ffffff"
  },
  "dark": {
    "accent": "oklch(76% 0.13 200)"
  }
}

The file layers over the selected built-in theme. A token you leave out keeps the built-in’s value, so the example above is complete: it changes the accent and nothing else. A palette you leave out keeps that whole mode on the built-in.

Rule Detail
name Shown on the custom card in Settings. Missing or blank reads Custom.
Keys Token names from the tables below, without the leading --.
Values Any CSS color the app’s WebView accepts: hex such as #1b1035, rgb(), hsl(), oklch(), or color-mix().
Applying Saving the file applies it. So does a change from another editor, from the CLI, or from sync.
Mistakes Unknown tokens and unusable values are skipped one by one and listed under the switch. See When the file is broken.

Core tokens

These ten paint almost everything. Most other tokens are mixed from them, so changing a core token also moves everything derived from it.

Token What it paints
bg The editor and the main page
bg-sidebar The file tree, the tab bar, and the toolbar
bg-hover Rows and buttons under the mouse
bg-active The selected file in the tree and the active tab
fg Body text and headings
fg-muted Secondary text such as dates, folder paths, and finished tasks
border Dividing lines and table rules
accent Links, primary buttons, ticked checkboxes, and focus rings
accent-contrast Text drawn on top of the accent color
danger Delete actions and error messages

A good way to start is with three colors: a background, a text color, and one accent. Make bg-sidebar, bg-hover, bg-active, and border small lightness steps away from bg, and the derived tokens fall into place.

Derived tokens

Each of these follows the core tokens by default. Override one by name when the computed value does not suit your palette.

Token Default
card-bg bg
hairline fg at 8% over transparent
control-bg card-bg
control-bg-hover bg-hover
control-border fg at 18% over bg
switch-off-bg fg at 20% over transparent
scrollbar-thumb fg at 16% over transparent
scrollbar-thumb-hover fg at 28% over transparent
scrollbar-thumb-active accent at 55% over transparent
editor-cursor fg
editor-selection-bg accent at 20% over transparent
editor-source-bg bg
editor-source-fg fg
editor-gutter-bg fg at 5% over bg
editor-gutter-fg fg-muted at 70% over bg
editor-active-line-bg fg at 3% over transparent
editor-active-gutter-bg fg at 10% over bg
danger-bg-hover danger at 9% over transparent
task-done-strike fg-muted at 45% over transparent
task-checkbox-border control-border

The editor-source-*, editor-gutter-*, and editor-active-* tokens color source mode, the raw Markdown view with line numbers described in The editor.

Per-mode tokens

These have one fixed default for light mode and another for dark mode. They do not follow your core colors, so a dark palette that leaves them out keeps whatever the current mode provides.

Group Tokens
Dialogs and switches overlay, shadow, switch-thumb
Warning banners warning-bg, warning-border, warning-fg
Source mode syntax editor-syntax-heading, editor-syntax-strong, editor-syntax-emphasis, editor-syntax-link, editor-syntax-string, editor-syntax-keyword, editor-syntax-comment, editor-syntax-number, editor-syntax-meta, editor-syntax-code, editor-syntax-quote, editor-syntax-list, editor-syntax-punctuation
Version history diffs diff-add-bg, diff-add-word-bg, diff-add-fg, diff-del-bg, diff-del-word-bg, diff-del-fg, diff-hunk-bg, diff-hunk-fg
File badges badge-md, badge-js, badge-json, badge-ts, badge-py, badge-rs, badge-html, badge-css, badge-pdf, badge-doc, badge-sheet, badge-slides, badge-image, badge-txt, badge-generic

Two exceptions follow a core token in both modes: badge-md uses accent, and diff-hunk-fg uses fg-muted. The file badges are the small colored letters beside each file in the sidebar. The diff tokens color the comparison view in Version history.

Contrast targets

Contrast ratio measures how far text stands out from what is behind it, from 1:1 (invisible) to 21:1 (black on white). Every built-in theme is tested against these minimums in both modes:

Pair Minimum
fg on bg 7:1
fg on bg-sidebar 7:1
fg-muted on bg 4.5:1 (7:1 in the Contrast theme)
accent on bg 4.5:1
accent-contrast on accent 4.5:1

Jotura does not check your file. Run your hex values through any WCAG contrast checker. In oklch() the first number is lightness, so raising or lowering it fixes contrast without shifting the hue.

One look in both modes

The seeded file holds separate light and dark palettes. For a single look, such as a dark theme that never turns light, put the same palette under both light and dark, then set Mode to match. Tokens your file leaves out still come from the current mode. The per-mode tokens are where this shows: a dark palette displayed in light mode keeps light mode’s dark badge letters and light diff backgrounds unless the file sets them too.

Starter palettes

Ten complete theme files are available to download. Each puts one palette under both light and dark, sets between 38 and 41 tokens including the syntax, diff, and warning colors, and looks the same in either mode. Download one, paste its contents into Jotura/theme.json, and adjust from there.

Palette Look fg on bg
Synthwave Dark. Deep purple with hot magenta. 15.5:1
Phosphor Dark. A green terminal, every color a shade of green. 15.9:1
Blueprint Dark. Architect’s blue with yellow accents. 10.1:1
Abyss Dark. Near-black ocean with glowing cyan. 15.8:1
Molten Dark. Charcoal and lava orange. 16.5:1
Aurora Dark. Midnight navy with a mint accent. 16.3:1
Risograph Light. Cream paper, blue ink, fluorescent pink. 11.2:1
Bubblegum Light. Pastel pink with a teal accent. 14.3:1
Brutalist Light. White page, yellow sidebar, black rules, blue links. 21:1
Game Boy Light. The original handheld’s four greens. 6.0:1

Nine of the ten meet every target above. Game Boy has only four shades to work with, so its text reaches 6.0:1 on the page and 5.0:1 on the sidebar, short of 7:1.

Editing from the command line

Jotura/theme.json is a plain file, so the jotura CLI reads and writes it like a note. A path without an .md extension has no frontmatter, so every operation covers the whole file. Replace the whole theme with a downloaded palette:

jotura write Jotura/theme.json < synthwave.json

Change one color. The Synthwave file sets its accent under both palettes, so the match appears twice and needs --all. Without it, the command exits 4 (Ambiguous) and writes nothing.

jotura edit Jotura/theme.json --replace '"accent": "#ff4fb0"' --with '"accent": "#ff7ac4"' --all

The desktop app picks up either change while it runs. If the switch is off, the file waits: turning Custom theme on later uses the file you wrote and seeds nothing. The safe-edit loop with --if-hash is in Editing from the CLI.

When the file is broken

Jotura applies whatever it can use from the file and lists each problem under the switch in Settings. Only a file it cannot read as a theme at all falls back to the built-in entirely.

Problem What you see What shows on screen
The file is not valid JSON Invalid JSON: followed by the parser’s message The built-in theme, unchanged
The file is JSON but not an object Theme file must be a JSON object The built-in theme
Neither light nor dark is an object Theme file needs a "light" or "dark" object The built-in theme
One palette is not an object "light" must be an object; ignored The other palette still applies
A token name Jotura does not know light.<name>: unknown token; ignored Every other token still applies
A value that is not a usable color dark.<name>: not a colour the app can use; ignored Every other token still applies
The file is deleted or missing Jotura/theme.json is missing from the vault. with a Recreate button The built-in theme

Recreate writes a fresh file seeded from the built-in theme currently selected. Turning Custom theme off stops using the file and never deletes it.

Limits

  • Colors only. Fonts and font sizes are separate rows under Appearance, and layout, spacing, and icons cannot change.
  • One active theme file per vault. Keep spares elsewhere in the vault and copy the one you want into Jotura/theme.json.
  • No custom CSS. A theme or CSS snippet written for another app does not apply, and copying its colors into this file is the closest equivalent.
  • Desktop only. The Android app ignores the file.

Every other Appearance setting is in the Settings reference.