Themes

Theme System Architecture

A modular, isolated, and compositor-agnostic theming engine designed to “decorate” rather than “define” system functionality.

🏗️ Two-Tiered Architecture

The core philosophy of this theme system is strict isolation combined with modern defaults. We move away from a “blank slate” approach toward a system that is beautiful by default but remains fully customizable.

Tier 1: Global Defaults (The Base)

When modules.theme.active is set to null, the system employs a “Global Default” tier.

  • Palette: Standardized on Catppuccin Mocha for its high quality and broad community support.
  • Goal: Ensure the system feels premium and visually coherent out-of-the-box.
  • Implementation: Apps like Foot and WezTerm hardcode these defaults in their base Nix modules.

Tier 2: Active Theme (The Decoration)

When an active theme is selected (e.g., Alucard, Autumnal), it acts as a decorator.

  • Mechanism: The theme module populates modules.theme.colors and modules.theme.fonts.
  • Propagation: Applications “react” to these changes via mkIf (config.modules.theme.active != null) blocks.

🎨 Integration Levels

1. System Level (Hard-Linked)

Components that define the global “look and feel”:

  • GTK & QT (Kvantum): Centralized in modules/theme/default.nix.
  • WMs (Hyprland/Niri): Use hooks and native settings to apply the color palette to borders, gaps, and shadows.
  • Fonts: A unified fonts submodule provides aliases (mono, sans, terminal) that all apps must consume.

2. App Level (Reactive)

Applications that support native theming or internal configuration:

  • Terminal Emulators (Foot, WezTerm): They use a “Default + Override” pattern. They default to Catppuccin but dynamically generate their config based on the active theme’s hex values.
  • Shell (Zsh): Prompts are modularized and selectable via modules.theme.apps.zsh.prompt. Supported options include starship (modern default), matrix (retro green), and p10k (Powerlevel10k integration).
  • Tmux: Support for dynamic theme switching via modules.theme.apps.tmux.theme. Catppuccin settings are modularized under modules.shell.tmux.catppuccin, including support for status bar transparency.
  • Rofi: The theme selection is centralized in modules.theme.apps.rofi.theme (e.g., gemini, autumnal, matrix).

🛠️ Themes Upgrade Plan (Roadmap)

To improve flexibility and scale, the system is moving toward these goals:

  1. Standardized Color Submodule: Move all theme colors into a strictly typed Nix submodule to catch errors at evaluation time (e.g., missing highlight or border colors).
  2. Catppuccin-First Strategy: Leverage the vast Catppuccin ecosystem. If an app has an official Catppuccin theme, we prefer using it as the default/fallback before falling back to generic hex injection.
  3. Modularized apps.nix: As more apps are added, apps.nix will be split into functional categories (e.g., apps/browsers.nix, apps/terminals.nix, apps/shells.nix) to keep the logic manageable.
  4. Live Reloading: Enhance hey hook reload to ensure that changing the active theme in a host config results in a seamless transition without restarting sessions.

🖋️ Adding a New Theme

  1. Create modules/themes/<name>/default.nix.
  2. Define mkIf (cfg.active == "<name>").
  3. Populate modules.theme.colors (following the ANSI + Types spec) and modules.theme.fonts.
  4. Register the folder in modules/themes/default.nix.