A palette is the set of colors Noctalia paints itself with, and that templates push out to your other apps.
This repo is the community palette source. Merged palettes are served from
https://api.noctalia.dev/palette/<name> and appear in Settings -> Color scheme, where any user can pick them.
PRs are welcome.
One directory per palette. The directory name is the palette name users see, so it must begin with an uppercase
letter; spaces are fine (Rose Pine Moon/). Each directory must contain exactly one JSON file named exactly after it,
including case:
Rose Pine Moon/
Rose Pine Moon.json
registry.json at the repo root indexes every palette. It is generated by CI, so never edit it or include it in a
commit. A PR that touches it is failed automatically.
A palette defines a dark and a light variant. Both are required: users switch between them, and a palette that only
looks right in one is a palette that breaks for half of them.
Each variant has 16 color roles plus a terminal block:
Copy an existing palette as your starting point; every key above is required in both variants.
Colors are #rrggbb, exactly six hex digits. No named colors, no shorthand, and no alpha: Noctalia drops a
value it cannot parse and the role silently falls back to something else, so #00000020 does not give you a
translucent shadow, it gives you a broken one. CI rejects anything that is not six hex digits.
Every mOnX has to be legible on its mX. That is the whole job of those pairs, and it is what reviewers look at
first. CI measures each pair as a WCAG contrast ratio: below 2.0:1 the check fails (that text is not readable at
any size), and 2.0:1 to 3.0:1 is reported as a warning for the reviewer to weigh. Light variants are where this
bites, because a near-white mOnPrimary on a mid-tone accent is usually the pair that goes thin.
The Theming docs describe what each role drives.
Drop your JSON into the palettes/ folder of your Noctalia config directory and point the config at it:
[theme]
source = "custom"That is the same loader the shipped palettes go through, without touching the registry. Switch between dark and light, open a few panels, and open a terminal to check the terminal colors.
Run the contrast check the way CI will, before you open the PR (needs jq):
./.github/workflows/contrast-check.sh "My Palette"/*.json # add --all to list passing pairs tooOpen a PR against main. CI checks every changed palette on each push: all required roles present, every color a
valid #rrggbb, and every mOnX legible on its mX. It comments on the PR with anything it finds.
- One palette per PR.
- Pick a name that is not already taken in this repo.
- Screenshots of Noctalia with your palette applied, in both dark and light (the PR template asks for these).
- Do not edit
registry.json.
- Documentation
- Discord
- Bugs in Noctalia itself, rather than in a palette, belong in noctalia.
{ "dark": { "mPrimary": "#a9b665", // accent: active elements, highlights "mOnPrimary": "#282828", // text and icons drawn on top of mPrimary "mSecondary": "#d8a657", "mOnSecondary": "#282828", "mTertiary": "#7db2ba", "mOnTertiary": "#282828", "mError": "#ea6962", "mOnError": "#282828", "mSurface": "#282828", // the main background "mOnSurface": "#d4be98", // the main text color "mSurfaceVariant": "#32302f", // raised or inset surfaces "mOnSurfaceVariant": "#a89984", "mOutline": "#504945", // borders and dividers "mShadow": "#000000", "mHover": "#a9b665", // hover state "mOnHover": "#282828", "terminal": { "normal": { "black": "#282828", "red": "#ea6962", "green": "#a9b665", "yellow": "#d8a657", "blue": "#7db2ba", "magenta": "#d3869b", "cyan": "#89b482", "white": "#d4be98" }, "bright": { "black": "#928374", "red": "#ea6962", "green": "#a9b665", "yellow": "#d8a657", "blue": "#7db2ba", "magenta": "#d3869b", "cyan": "#89b482", "white": "#dfbf8e" }, "foreground": "#d4be98", "background": "#282828", "selectionFg": "#282828", "selectionBg": "#d4be98", "cursorText": "#282828", "cursor": "#d4be98" } }, "light": { } // the same shape again }