Implementation Guide

Juna acts as a transparent layer. It provides the abstractions for system-wide consistency while leaving the low-level implementation details in your hands.


Standard Configuration

Every module in Juna is opt-in. You decide which parts of your system Juna is allowed to touch.

{pkgs, ...}: {
  juna = {
    enable = true;
    theme = "nord";

    # Assets
    wallpapers.enable = true;

    # Development Tools (CLI)
    cli = {
      # Standard static application
      helix.enable = true;
      
      # Application with optional live-reload enabled
      nvim = {
        enable = true;
        themeAutoReload = true; 

        # Customize domain theme
        themePackage = pkgs.vimPlugins.gruvbox;
        themeName = "gruvbox";
        settings = ''
          let g:gruvbox_contrast_dark = 'medium'
          let g:gruvbox_italic = 0
          let g:gruvbox_bold = 0
          let g:gruvbox_invert_selection = 0
        '';
      };
    };

    # Desktop Environment
    desktop = {
      foot = {
        enable = true;
        liveThemeReload = false; # Stick to standard Nix activation

        # userShell is not necessary, since `liveThemeReload` is disabled
        # userShell = "${pkgs.fish}/bin/fish"; 
      };
      gtk.enable = true;
    };
  };
}

Using junaTheme for custom modules

Juna is built to be extensible. If an application isn't supported out of the box, you can use junaTheme for system-wide consistency, or junaAllThemes to pin a specific colorscheme to a specific app.

Here is an implementation for alacritty demonstrating theme pinning:

{ 
  config, 
  junaTheme,     # The globally active theme
  junaAllThemes,  # Every theme registered in Juna
  junaLib, 
  ... 
}: {
  programs.alacritty = {
    enable = true;
    settings.colors = let
      # OPTION A: Follow the global system theme
      palette = junaTheme.colors; 

      # OPTION B: Pin this app to a specific theme (e.g., Catppuccin)
      # palette = junaAllThemes.catppuccin.colors;

      junaColors = {
        primary = {
          background = palette.base01;
          foreground = palette.base05;
        };
        normal = {
          black   = palette.base02;
          red     = palette.base11;
          # ... (rest of colors)
        };
      };
    in
      junaColors;
  };
}


Why keep junaAllThemes available?

  • Domain Isolation: Sometimes you want your editor (Neovim) in a high-contrast theme like Tokyo-Night while your desktop environment remains in a muted Everforest. junaAllThemes allows you to pick pigments from any registered palette without breaking the Nix evaluation.
  • Theme Previewing: You can use this to hardcode specific modules to different themes to compare how Juna's Pigment Mapping handles different contrasts before committing to a global change.
  • The Full API: Because Juna passes these via _module.args, they are already evaluated. Accessing junaAllThemes."nord" is essentially free in terms of performance—it's just a lookup in an existing attribute set.

Key Concepts

Activation Flow

By default, Juna follows the standard Home Manager activation flow. When you run home-manager switch, Juna evaluates your chosen theme, maps the pigments to your enabled modules, and writes the resulting configurations to the Nix store.

Opt-in Performance

If you enable liveThemeReload for a module, Juna creates an auxiliary bridge in $XDG_CACHE_HOME/juna/. This is purely an optimization for users who frequently swap themes and want to avoid the latency of a full system generation. If you don't need it, don't enable it — Juna remains functional without it.