Theming (Stylix)¶
Last Updated: 2026-09-01
The problem¶
A consistent look across a desktop means keeping colours in sync across the compositor, terminals, editors, GTK/Qt, and every applet. Maintaining those palettes by hand guarantees they drift.
The solution¶
Theming is centralised through Stylix using a single base16 palette.
Every surface derives its colours from config.lib.stylix.colors rather than
hard-coding hex values.
Where the palette comes from¶
The active Omarchy theme is the source of truth for colours.
modules/desktop/stylix-theme.nix reads the theme name from
nixarchy-theme.nix at the flake root, loads that theme's colors.toml out of
the Nixarchy package, maps its named roles onto the sixteen base16 slots and
hands the result to Stylix.
omarchy theme set X
├── retints the 24 files Omarchy owns → immediately
└── theme-set.d hook writes X to nixarchy-theme.nix
└── stylix-theme.nix → Stylix → Plymouth, GRUB, console,
GTK, Qt, fonts, home-manager targets → next rebuild
Three consequences:
- Everything Omarchy cannot reach at runtime follows at the next rebuild, not instantly.
- Switching a theme leaves the tree dirty, and
nhsrefuses a dirty tree. - p510 follows the same palette as the workstations, because
inputs.nixarchyis flake-wide.
Omarchy's colors.toml is a named-role palette rather than base16, but its roles
cover all sixteen slots one-for-one. Three stock themes (last-horizon,
solitude, white) ship no orange or brown, so base09 and base0F fall
back to yellow and muted rather than failing evaluation.
Reach the package through inputs
Use inputs.nixarchy, never config.programs.nixarchy.package. Nixarchy
consumes Stylix, so reading its config from the module that defines
stylix.base16Scheme closes the module fixpoint and evaluation dies with
infinite recursion.
If the theme name is not present in the package — a user theme under
~/.config/omarchy/themes/, which the flake cannot see — the build falls back to
the checked-in YAML scheme rather than failing.
The fallback theme¶
The fallback theme is defined once in hosts/common/shared-variables.nix:
baseTheme = {
scheme = "alien-hud";
wallpaper = ../../assets/wallpapers/amdgruvorange.png;
cursor = { name = "Bibata-Modern-Classic"; size = 16; };
font = {
mono = "Adwaita Mono";
sans = "Noto Sans";
serif = "Noto Serif";
};
opacity = { desktop = 1.0; terminal = 1.0; popups = 1.0; };
};
What derives from the palette¶
Surfaces that cannot consume Stylix automatically are wired to it explicitly:
- GNOME Terminal and Zellij — colours generated from
config.lib.stylix.colors. - Plymouth, GRUB and the Linux console — themed through Stylix, which is the only way they can follow Omarchy at all.
- GTK and Qt, fonts, cursor and the icon theme (Papirus, recoloured).
- COSMIC — a full RON palette (all 30 fields) is written from the same
source. COSMIC itself is parked (
desktop.cosmic.enable = falseon every host), but the writer is kept wired for an easy re-enable.
Because they all read one palette, changing scheme re-themes the entire stack
in a single rebuild.
nix-colors removed
An earlier setup used a standalone nix-colors input. It was removed in
favour of deriving everything from Stylix directly — one source of truth,
one dependency fewer.
Opacity¶
Terminal and popup opacity are pinned to 1.0. Transparency was disabled
deliberately: it caused rendering issues under COSMIC/GTK. The structure is kept
so it can be re-enabled per host if a future desktop handles it cleanly.
Omarchy manages its own window opacity and blur through
~/.config/hypr/; those are runtime settings and are not driven from here.
Per-host wallpaper¶
The base theme carries a single wallpaper. Hosts may override it in their
variables.nix; the mechanism is intentionally minimal because the rest of the
palette is shared.
See also: Desktop (Nixarchy / Omarchy on Hyprland).