From 877da19770a0fcd99902868c3c07a5dc37990836 Mon Sep 17 00:00:00 2001 From: Bernardo Magri Date: Fri, 24 Apr 2026 18:20:54 +0100 Subject: [PATCH] feat: make VM and live ISO match an installed Nomarchy - Migrate VM and graphical ISO to home-manager.nixosModules.home-manager; drop the standalone-HM sudo-based activation script (ran HM against /root because HOME wasn't reset) in flake.nix, core/system/vm-guest.nix, hosts/live-iso.nix. - Run swaybg as nomarchy-wallpaper.service instead of a silent Hyprland exec-once so failures surface in systemctl. - Skip the battery monitor unit on hosts without /sys/class/power_supply/BAT* (VMs, desktops). - Don't wrap walker --dmenu in uwsm-app; redirect setsid background std-fds in nomarchy-launch-walker so $(menu ...) in nomarchy-menu doesn't hang. - Restart waybar/walker via systemctl --user rather than pkill + uwsm-app to stop the post-theme-switch color race. - Wire nomarchy-restart-walker/-waybar into nomarchy-theme-set so themes that only change the imported CSS reload correctly. - Waybar: pin #custom-nomarchy to the Nomarchy font and use the U+F000 codepoint so the logo shows across all themes. - Auto-install the correct icon-theme package per palette via a new nomarchyLib.iconThemePackage helper in lib/default.nix; Everforest now actually renders for summer-night. - Pre-cache every theme's HM generation: new packages.allThemeVariants flake output and nomarchy-themes-prebuild script so theme switches are cache-only (no Stylix rebuild, no downloads). - Add nomarchy-test-live-iso to boot the graphical ISO in QEMU the same way nomarchy-test-vm does, with virtio-gpu support added to live-iso.nix. - Installer-generated home.nix/system.nix now ship a curated, commented app menu (btop/fastfetch/chromium on by default) plus optional system services (Docker, libvirtd, Tailscale, Syncthing, Flatpak, Steam). - nomarchy-test-vm now wipes the stale nomarchy.qcow2 before launch. - Remove obsolete GEMINI.md and PLAN.md. Co-Authored-By: Claude Opus 4.7 --- GEMINI.md | 49 -------- PLAN.md | 32 ----- .../nomarchy/default/hypr/autostart.conf | 3 +- core/system/vm-guest.nix | 19 +-- features/default.nix | 8 +- features/desktop/hyprland/default.nix | 20 +++ .../desktop/scripts/nomarchy-restart-walker | 11 +- .../desktop/scripts/nomarchy-restart-waybar | 11 ++ features/desktop/waybar/config/config.jsonc | 2 +- features/desktop/waybar/config/style.css | 8 ++ features/scripts/battery-monitor.nix | 4 + features/scripts/utils/nomarchy-launch-walker | 21 +++- features/scripts/utils/nomarchy-test-live-iso | 47 +++++++ features/scripts/utils/nomarchy-test-vm | 4 + flake.nix | 76 +++++++++--- hosts/live-iso.nix | 25 ++-- installer/install.sh | 115 +++++++++++++++++- lib/default.nix | 15 +++ themes/engine/scripts/nomarchy-theme-set | 11 ++ .../engine/scripts/nomarchy-themes-prebuild | 25 ++++ themes/engine/stylix.nix | 10 +- 21 files changed, 368 insertions(+), 148 deletions(-) delete mode 100644 GEMINI.md delete mode 100644 PLAN.md create mode 100755 features/scripts/utils/nomarchy-test-live-iso create mode 100755 themes/engine/scripts/nomarchy-themes-prebuild diff --git a/GEMINI.md b/GEMINI.md deleted file mode 100644 index dbaa564..0000000 --- a/GEMINI.md +++ /dev/null @@ -1,49 +0,0 @@ -The Nomarchy UI/UX Audit Mega-Prompt -System Role: You are a Lead Linux UI/UX Architect and Wayland Desktop Environment QA Engineer. Your task is to perform a rigorous, line-by-line syntax and logic audit of the provided configuration files (dotfiles) for the Nomarchy OS desktop environment. - -The Goal: Ensure zero syntax errors, zero deprecated variables, and perfect path resolution across all Wayland compositors, bars, terminals, and launchers. - -Execution Directives (STRICT COMPLIANCE REQUIRED): -Your mindset is highly skeptical. Assume these config files contain deprecated syntax, trailing commas, broken script paths, and hardcoded variables. You are forbidden from providing a generic summary until you have completed the Forced UI Audit Protocol for every single file. - -The Forced UI Audit Protocol: -For every file provided, you MUST output a block formatted exactly like this: - -[UI-AUDIT: filename.extension] - -Parser Check: (Identify the language: JSON, TOML, CSS, Hyprland-conf. Explicitly state if you checked for language-specific strictness, like trailing commas in JSON). - -Deprecation Check: (Are any variables or syntax structures outdated based on the latest stable releases of the software?) - -Path & Dependency Check: (List any shell scripts, fonts, or external commands referenced in this file. Are they valid?) - -Status: (Pass / Fail / Warning) - -Specific Application Directives (Hunt for these common failures): - -Hyprland (hyprland.conf): - -Scrutinize shadow and blur variables. (Hyprland recently changed drop_shadow = true to the decoration:shadow { enabled = true } syntax). Check for valid color variable injection (e.g., $base00). - -Verify exec-once paths. Do not allow relative paths for critical startup scripts. - -Waybar (config & style.css): - -JSON Strictness: Waybar uses strict JSON. You MUST check for and flag any trailing commas, missing quotes, or unescaped characters. - -CSS Scope: Verify that standard GTK CSS properties are used. Ensure font families have valid fallbacks. - -Alacritty (alacritty.toml): - -Format Check: Ensure the file is using TOML syntax, NOT the deprecated YAML syntax. Check that font definitions match the correct TOML schema. - -Launchers (Walker / Rofi): - -Verify that the theme variables match the overarching system color palette. Check that terminal execution commands match the default terminal (Alacritty). - -Final Deliverable: -After completing the audit blocks for all files, provide a "UI/UX Incident Report". - -For any file that failed, quote the broken line, explain why the target program will reject it (e.g., "Waybar will crash on launch due to a trailing comma on line 42"), and provide the exact corrected code block. - -Begin the Forced UI Audit Protocol now. diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index bd1cfe3..0000000 --- a/PLAN.md +++ /dev/null @@ -1,32 +0,0 @@ -# UI/UX Audit Progress - -## Core Desktop -- [x] Hyprland Template: `themes/templates/hyprland.conf.tpl` -- [x] Hyprlock Template: `themes/templates/hyprlock.conf.tpl` -- [x] Theme-specific Hyprland configs: - - [x] `features/desktop/hyprland/themes/kanagawa/hyprland.conf` - - [x] `features/desktop/hyprland/themes/lumon/hyprland.conf` - - [x] `features/desktop/hyprland/themes/nord/hyprland.conf` - - [x] `features/desktop/hyprland/themes/retro-82/hyprland.conf` - - [x] `features/desktop/hyprland/themes/summer-night/hyprland.conf` -- [x] Waybar: `features/desktop/waybar/default.nix` - -## Launchers & Terminals -- [x] Walker Config: `core/home/config/nomarchy/default/hypr/apps/walker.conf` -- [x] Walker Desktop: `core/home/config/nomarchy/default/walker/walker.desktop` -- [x] Alacritty Template: `themes/templates/alacritty.toml.tpl` -- [x] Alacritty Screensaver: `core/home/config/nomarchy/default/alacritty/screensaver.toml` -- [x] Kitty Template: `themes/templates/kitty.conf.tpl` -- [x] Ghostty Template: `themes/templates/ghostty.conf.tpl` - -## Applications & Templates -- [x] Btop Theme: `themes/templates/btop.theme.tpl` -- [x] SwayOSD Style: `themes/templates/swayosd.css.tpl` -- [x] Mako Template: `themes/templates/mako.ini.tpl` -- [x] Chromium Theme: `themes/templates/chromium.theme.tpl` -- [x] Chromium Flags: `core/home/config/chromium-flags.conf` -- [x] Brave Flags: `core/home/config/brave-flags.conf` -- [x] Starship: `core/home/config/starship.toml` -- [x] Obsidian Style: `themes/templates/obsidian.css.tpl` -- [x] Ghostty Config: `themes/templates/ghostty.conf.tpl` -- [x] Keyboard RGB: `themes/templates/keyboard.rgb.tpl` diff --git a/core/home/config/nomarchy/default/hypr/autostart.conf b/core/home/config/nomarchy/default/hypr/autostart.conf index ce857ec..c49c01c 100644 --- a/core/home/config/nomarchy/default/hypr/autostart.conf +++ b/core/home/config/nomarchy/default/hypr/autostart.conf @@ -2,7 +2,8 @@ exec-once = uwsm-app -- hypridle exec-once = uwsm-app -- mako # exec-once = uwsm-app -- waybar exec-once = uwsm-app -- fcitx5 --disable notificationitem -exec-once = uwsm-app -- swaybg -i ~/.config/nomarchy/current/background -m fill +# swaybg is started as a systemd user service (nomarchy-wallpaper.service) +# so failures surface in logs and the wallpaper survives Hyprland restarts. exec-once = uwsm-app -- swayosd-server exec-once = nomarchy-on-boot diff --git a/core/system/vm-guest.nix b/core/system/vm-guest.nix index e20aadf..5d95487 100644 --- a/core/system/vm-guest.nix +++ b/core/system/vm-guest.nix @@ -1,19 +1,10 @@ -{ inputs, lib, pkgs, homeActivationPackage ? null, ... }: +{ inputs, lib, pkgs, ... }: { - # Pre-activate standalone home-manager if provided - system.activationScripts.home-manager-activate = lib.mkIf (homeActivationPackage != null) { - text = '' - USER_HOME="/home/nomarchy" - if [ ! -d "$USER_HOME" ]; then - mkdir -p "$USER_HOME" - chown nomarchy:users "$USER_HOME" - fi - # Run activation as the nomarchy user - ${pkgs.sudo}/bin/sudo -u nomarchy ${homeActivationPackage}/activate - ''; - deps = [ "users" ]; - }; + # Home Manager activation is provided by the home-manager.nixosModules.home-manager + # module wired up in flake.nix. It runs as a systemd user service per user and + # deploys ~/.config/hypr, ~/.config/nomarchy, ~/.config/waybar, etc. before the + # graphical session starts. # Shared VM configuration virtualisation.vmVariant = { diff --git a/features/default.nix b/features/default.nix index bf7f645..af79156 100644 --- a/features/default.nix +++ b/features/default.nix @@ -45,8 +45,6 @@ in colorScheme = lib.mkDefault (nomarchyLib.getColorScheme config.nomarchy.theme); - nixpkgs.config.allowUnfree = true; - # Enable neovim program module (required for stylix integration) programs.neovim.enable = lib.mkDefault true; @@ -83,9 +81,9 @@ in swaybg rofi-wayland - # Theming - yaru-theme - everforest-gtk-variant + # Theming — cursor package stays here; icon theme packages are pulled in + # dynamically by themes/engine/stylix.nix via nomarchyLib.iconThemePackage + # so switching to e.g. summer-night auto-installs everforest-gtk-theme. bibata-cursors ]); } diff --git a/features/desktop/hyprland/default.nix b/features/desktop/hyprland/default.nix index 42d4899..edd661e 100644 --- a/features/desktop/hyprland/default.nix +++ b/features/desktop/hyprland/default.nix @@ -50,4 +50,24 @@ in xdg.configFile."hypr/bindings.conf".source = lib.mkDefault ./config/bindings.conf; xdg.configFile."hypr/looknfeel.conf".source = lib.mkDefault ./config/looknfeel.conf; xdg.configFile."hypr/autostart.conf".source = lib.mkDefault ./config/autostart.conf; + + # Run swaybg as a proper systemd user service rather than a Hyprland exec-once. + # exec-once fails silently (black screen with no visible error) when timing + # against uwsm's graphical-session target is off; a service surfaces failures + # via `systemctl --user status nomarchy-wallpaper` and auto-restarts. + systemd.user.services.nomarchy-wallpaper = { + Unit = { + Description = "Nomarchy desktop wallpaper (swaybg)"; + PartOf = [ "graphical-session.target" ]; + After = [ "graphical-session.target" ]; + }; + Service = { + ExecStart = "${pkgs.swaybg}/bin/swaybg -i %h/.config/nomarchy/current/background -m fill"; + Restart = "on-failure"; + RestartSec = "2"; + }; + Install = { + WantedBy = [ "graphical-session.target" ]; + }; + }; } diff --git a/features/desktop/scripts/nomarchy-restart-walker b/features/desktop/scripts/nomarchy-restart-walker index fb1a9ea..3357eee 100755 --- a/features/desktop/scripts/nomarchy-restart-walker +++ b/features/desktop/scripts/nomarchy-restart-walker @@ -1,11 +1,18 @@ #!/bin/bash +# Walker (with runAsService = true) and elephant are Home Manager user +# services. Restart via systemd so the new process inherits the full graphical +# session environment — the pkill/uwsm-app dance left a window where the +# launcher would come back up with stale theming. + restart_services() { - if systemctl --user is-enabled elephant.service &>/dev/null; then + if systemctl --user list-unit-files elephant.service >/dev/null 2>&1; then systemctl --user restart elephant.service fi - if systemctl --user is-enabled app-walker@autostart.service &>/dev/null; then + if systemctl --user list-unit-files walker.service >/dev/null 2>&1; then + systemctl --user restart walker.service + elif systemctl --user is-enabled app-walker@autostart.service &>/dev/null; then systemctl --user restart app-walker@autostart.service else echo -e "\e[31mUnable to restart Walker -- RESTART MANUALLY\e[0m" diff --git a/features/desktop/scripts/nomarchy-restart-waybar b/features/desktop/scripts/nomarchy-restart-waybar index 832775c..041c848 100755 --- a/features/desktop/scripts/nomarchy-restart-waybar +++ b/features/desktop/scripts/nomarchy-restart-waybar @@ -1,3 +1,14 @@ #!/bin/bash +# Waybar is provided as a Home Manager user service +# (programs.waybar.systemd.enable = true), so the right way to restart it is +# via systemd. `pkill + uwsm-app` races with HM's sd-switch on theme changes +# and sometimes lands the new waybar without a full environment, producing +# the "wrong colors after theme switch" symptom. + +if systemctl --user list-unit-files waybar.service >/dev/null 2>&1; then + exec systemctl --user restart waybar.service +fi + +# Fallback for systems where waybar isn't managed by systemd. nomarchy-restart-app waybar diff --git a/features/desktop/waybar/config/config.jsonc b/features/desktop/waybar/config/config.jsonc index 4fad304..d7329ff 100644 --- a/features/desktop/waybar/config/config.jsonc +++ b/features/desktop/waybar/config/config.jsonc @@ -40,7 +40,7 @@ } }, "custom/nomarchy": { - "format": "a", + "format": "", "on-click": "nomarchy-menu", "on-click-right": "xdg-terminal-exec", "tooltip-format": "Nomarchy Menu\n\nSuper + Alt + Space" diff --git a/features/desktop/waybar/config/style.css b/features/desktop/waybar/config/style.css index 2638ca5..3ae29db 100644 --- a/features/desktop/waybar/config/style.css +++ b/features/desktop/waybar/config/style.css @@ -39,6 +39,14 @@ margin: 0 7.5px; } +/* The Nomarchy glyph lives at U+F000 in the dedicated "Nomarchy" font. + Nerd Fonts (used by default) also have U+F000 but render it as a glass + icon, so we have to pin the family for this module. */ +#custom-nomarchy { + font-family: Nomarchy; + font-size: 20px; +} + #tray { margin-right: 16px; } diff --git a/features/scripts/battery-monitor.nix b/features/scripts/battery-monitor.nix index d646887..9b5aa66 100644 --- a/features/scripts/battery-monitor.nix +++ b/features/scripts/battery-monitor.nix @@ -5,6 +5,9 @@ Unit = { Description = "Nomarchy Battery Monitor Check"; After = [ "graphical-session.target" ]; + # Skip on hosts with no battery (VMs, desktops) — otherwise the + # monitor script fails and degrades the user session. + ConditionPathExistsGlob = "/sys/class/power_supply/BAT*"; }; Service = { @@ -19,6 +22,7 @@ systemd.user.timers.nomarchy-battery-monitor = { Unit = { Description = "Nomarchy Battery Monitor Timer"; + ConditionPathExistsGlob = "/sys/class/power_supply/BAT*"; }; Timer = { diff --git a/features/scripts/utils/nomarchy-launch-walker b/features/scripts/utils/nomarchy-launch-walker index be63abd..411bdc5 100644 --- a/features/scripts/utils/nomarchy-launch-walker +++ b/features/scripts/utils/nomarchy-launch-walker @@ -3,14 +3,27 @@ # Wrapper to launch walker with elephant provider, or fallback to rofi if walker is missing. if command -v walker >/dev/null 2>&1; then - # Ensure elephant is running before launching walker + # The setsid backgrounded commands below MUST redirect all std fds to + # /dev/null. If they inherit stdout from a $(...) caller (e.g. nomarchy-menu + # doing `$(menu ...)`), bash waits for those fds to close on every return, + # which hangs the terminal after each menu selection. if ! pgrep -x elephant > /dev/null; then - setsid uwsm-app -- elephant & + setsid uwsm-app -- elephant /dev/null 2>&1 & + disown fi - # Ensure walker service is running if ! pgrep -f "walker --gapplication-service" > /dev/null; then - setsid uwsm-app -- walker --gapplication-service & + setsid uwsm-app -- walker --gapplication-service /dev/null 2>&1 & + disown + fi + + # dmenu mode reads stdin and is invoked many times in quick succession + # by nomarchy-menu. Wrapping each call in uwsm-app (systemd-run --scope) + # creates a fresh transient scope per invocation, which breaks chained + # submenus — subsequent walker calls don't see a usable stdin and exit + # without showing anything. Invoke walker directly for dmenu. + if [[ "$*" == *"--dmenu"* ]]; then + exec walker "$@" fi exec uwsm-app -- walker --width 644 --maxheight 300 --minheight 300 "$@" diff --git a/features/scripts/utils/nomarchy-test-live-iso b/features/scripts/utils/nomarchy-test-live-iso new file mode 100755 index 0000000..4406e33 --- /dev/null +++ b/features/scripts/utils/nomarchy-test-live-iso @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Build the Nomarchy graphical live ISO and boot it in QEMU for a +# try-before-install experience. The ISO is the `installerIsoGraphical` +# NixOS configuration — same Nomarchy system + Home Manager stack as +# `nomarchy-test-vm`, just wrapped in an installable live medium. + +set -e + +echo "Building Nomarchy Live ISO..." +nix build .#nixosConfigurations.installerIsoGraphical.config.system.build.isoImage + +ISO=$(ls -1 result/iso/*.iso 2>/dev/null | head -n 1) +if [ -z "$ISO" ]; then + echo "Error: ISO build succeeded but no .iso file found in result/iso/" + exit 1 +fi + +# Prefer UEFI with OVMF so the ISO boots the same way a modern install does. +# Fall back to BIOS if OVMF isn't available on this host. +OVMF_CANDIDATES=( + "/run/current-system/sw/share/OVMF/OVMF_CODE.fd" + "/run/current-system/sw/share/qemu/edk2-x86_64-code.fd" + "/nix/var/nix/profiles/system/sw/share/OVMF/OVMF_CODE.fd" +) +BIOS_ARG=() +for c in "${OVMF_CANDIDATES[@]}"; do + if [ -f "$c" ]; then + BIOS_ARG=(-bios "$c") + break + fi +done + +# KVM if the host supports it; software emulation otherwise. +ACCEL_ARG=() +if [ -r /dev/kvm ]; then + ACCEL_ARG=(-enable-kvm -cpu host) +fi + +echo "Launching ISO: $ISO" +exec qemu-system-x86_64 \ + "${ACCEL_ARG[@]}" \ + -m 4096 -smp 2 \ + "${BIOS_ARG[@]}" \ + -device virtio-vga-gl -display gtk,gl=on \ + -device virtio-net-pci,netdev=n0 -netdev user,id=n0 \ + -cdrom "$ISO" -boot d diff --git a/features/scripts/utils/nomarchy-test-vm b/features/scripts/utils/nomarchy-test-vm index 32aa46b..f8efa50 100755 --- a/features/scripts/utils/nomarchy-test-vm +++ b/features/scripts/utils/nomarchy-test-vm @@ -7,6 +7,10 @@ echo "Note: To test the INSTALLER, run 'nomarchy-test-installer' instead." nix build .#nixosConfigurations.default.config.system.build.vm if [ $? -eq 0 ]; then + # Drop any persisted VM disk so activation runs against fresh state. + # Without this, broken symlinks from a prior activation survive rebuilds + # and mask fixes on the next launch. + rm -f ./nomarchy.qcow2 echo "Success! Launching VM..." ./result/bin/run-nomarchy-vm else diff --git a/flake.nix b/flake.nix index 0cfb855..7e1433c 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,9 @@ }; outputs = { self, nixpkgs, nixos-hardware, disko, impermanence, home-manager, nix-colors, stylix, walker, ... } @ inputs: let + system = "x86_64-linux"; + lib = nixpkgs.lib; + # Overlays overlays = [ (final: prev: { @@ -43,13 +46,14 @@ }) ]; + pkgs = import nixpkgs { + inherit system overlays; + config.allowUnfree = true; + }; + # Helper to create standalone home configurations mkHome = { username, modules ? [] }: home-manager.lib.homeManagerConfiguration { - pkgs = import nixpkgs { - inherit (nixpkgs.legacyPackages.x86_64-linux) system; - inherit overlays; - config.allowUnfree = true; - }; + inherit pkgs; extraSpecialArgs = { inherit inputs; }; modules = [ ./features @@ -65,6 +69,23 @@ "nixos" = mkHome { username = "nixos"; }; "nomarchy" = mkHome { username = "nomarchy"; }; }; + + # Realise the full HM generation for every palette so theme switches hit + # the Nix cache instead of rebuilding Stylix outputs per swap. Each entry + # pins `nomarchy.theme` (and clears the wallpaper override so the theme's + # own default background is used) and exposes the generation's activation + # package under its theme name. + palettes = import ./themes/palettes; + themeNames = builtins.attrNames palettes; + themeVariantFor = themeName: (mkHome { + username = "nomarchy"; + modules = [{ + nomarchy.theme = lib.mkForce themeName; + nomarchy.wallpaper = lib.mkForce ""; + }]; + }).activationPackage; + allThemeVariants = pkgs.linkFarm "nomarchy-all-theme-variants" + (map (name: { inherit name; path = themeVariantFor name; }) themeNames); in { # Expose inputs for downstream use inherit inputs; @@ -94,43 +115,48 @@ # Graphical installer ISO (legacy, for users who prefer GUI) installerIsoGraphical = nixpkgs.lib.nixosSystem { - specialArgs = { - inherit inputs; - homeActivationPackage = homeConfigs."nixos".activationPackage; - }; + specialArgs = { inherit inputs; }; modules = [ - { + { nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.overlays = overlays; } "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix" + home-manager.nixosModules.home-manager ./hosts/live-iso.nix ./core { system.stateVersion = "25.11"; services.displayManager.autoLogin.enable = true; services.displayManager.autoLogin.user = "nixos"; + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "hm-bak"; + home-manager.extraSpecialArgs = { inherit inputs; }; + home-manager.users.nixos = { + imports = [ ./features ]; + home.stateVersion = "25.11"; + }; } ]; }; # Default configuration (VM and testing) default = nixpkgs.lib.nixosSystem { - specialArgs = { - inherit inputs; - homeActivationPackage = homeConfigs."nomarchy".activationPackage; - }; + specialArgs = { inherit inputs; }; modules = [ - { + { nixpkgs.hostPlatform = "x86_64-linux"; nixpkgs.overlays = overlays; } + home-manager.nixosModules.home-manager ./core/default.nix ./core/system/vm-guest.nix { system.stateVersion = "25.11"; networking.hostName = "nomarchy"; - + virtualisation.vmVariant.virtualisation.memorySize = 4096; virtualisation.vmVariant.virtualisation.cores = 2; @@ -143,11 +169,29 @@ services.displayManager.autoLogin.enable = true; services.displayManager.autoLogin.user = "nomarchy"; + + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "hm-bak"; + home-manager.extraSpecialArgs = { inherit inputs; }; + home-manager.users.nomarchy = { + imports = [ ./features ]; + home.stateVersion = "25.11"; + }; } ]; }; }; homeConfigurations = homeConfigs; + + packages.${system} = { + # Pre-cache every theme's Home Manager generation so subsequent + # `nomarchy-theme-set` swaps are cache hits (no Stylix rebuild, no + # downloads). Run once after install: + # nix build /etc/nomarchy#allThemeVariants --no-link + inherit allThemeVariants; + default = allThemeVariants; + }; }; } diff --git a/hosts/live-iso.nix b/hosts/live-iso.nix index 64f8fbd..07fac09 100644 --- a/hosts/live-iso.nix +++ b/hosts/live-iso.nix @@ -1,19 +1,8 @@ -{ config, pkgs, inputs, lib, homeActivationPackage, ... }: +{ config, pkgs, inputs, lib, ... }: { - # Pre-activate standalone home-manager for the live environment - system.activationScripts.home-manager-activate = { - text = '' - USER_HOME="/home/nixos" - if [ ! -d "$USER_HOME" ]; then - mkdir -p "$USER_HOME" - chown nixos:users "$USER_HOME" - fi - # Run activation as the nixos user - ${pkgs.sudo}/bin/sudo -u nixos ${homeActivationPackage}/activate - ''; - deps = [ "users" ]; - }; + # Home Manager activation for the nixos live user is provided by the + # home-manager.nixosModules.home-manager module wired up in flake.nix. environment.systemPackages = with pkgs; [ git @@ -35,9 +24,11 @@ # Ensure the live environment user has the necessary groups for graphical acceleration and audio users.users.nixos.extraGroups = [ "wheel" "video" "render" "audio" "networkmanager" ]; - # Graphics support for live environment - boot.initrd.kernelModules = [ "amdgpu" "radeon" "nouveau" "i915" ]; - services.xserver.videoDrivers = [ "amdgpu" "radeon" "nouveau" "modesetting" "fbdev" ]; + # Graphics support for live environment. + # `virtio` is a no-op on real hardware (no virtio-gpu PCI device) but lets + # the ISO render correctly when booted in QEMU via nomarchy-test-live-iso. + boot.initrd.kernelModules = [ "amdgpu" "radeon" "nouveau" "i915" "virtio_gpu" ]; + services.xserver.videoDrivers = [ "amdgpu" "radeon" "nouveau" "modesetting" "fbdev" "virtio" ]; environment.etc."install.sh" = { source = ../installer/install.sh; diff --git a/installer/install.sh b/installer/install.sh index c1cd952..d0fe29b 100755 --- a/installer/install.sh +++ b/installer/install.sh @@ -454,7 +454,8 @@ FLAKE_EOF } EOF - # system.nix + # system.nix — curated system-level options. Uncomment what you want and + # run \`sudo nixos-rebuild switch --flake /etc/nixos#default\` to apply. cat > /mnt/etc/nixos/system.nix << EOF { pkgs, ... }: { @@ -462,8 +463,18 @@ EOF $impermanence_opt + # System-wide packages. Most tools belong in home.nix instead — only put + # things here that need to be available to all users or to root (e.g. CLI + # tools used by sudo, system admin utilities). environment.systemPackages = with pkgs; [ home-manager + # --- CLI tools useful as root --- + # wget + # curl + # rsync + # htop + # tree + # tmux ]; services.displayManager.autoLogin.enable = true; @@ -475,20 +486,111 @@ EOF extraGroups = [ "networkmanager" "wheel" "video" "audio" "render" ]; }; + # --- Optional system services --- + # Uncomment to enable. Some require extra groups on your user (see below). + + # Containers / virtualization + # virtualisation.docker.enable = true; # adds "docker" group + # virtualisation.libvirtd.enable = true; # adds "libvirtd" group — needed for virt-manager + + # Networking / sync + # services.tailscale.enable = true; + # services.syncthing = { + # enable = true; + # user = "$USERNAME"; + # dataDir = "/home/$USERNAME"; + # }; + + # Printing + # services.printing.enable = true; + + # Flatpak (alternative app delivery) + # services.flatpak.enable = true; + # xdg.portal.enable = true; + + # Gaming (system-level — pairs with home.packages.steam) + # programs.steam.enable = true; + # programs.gamemode.enable = true; + system.stateVersion = "25.11"; } EOF - # home.nix (empty for user customization) + # home.nix — curated app menu. Uncomment what you want and run + # `nomarchy-env-update` to apply. cat > /mnt/etc/nixos/home.nix << 'EOF' { pkgs, ... }: { - # Add your personal packages here + # User-level packages (Home Manager). + # + # Nomarchy already ships a minimal desktop (firefox, thunar, mpv, imv, mako, + # hyprlock, swww, wl-clipboard, grim, slurp, rofi-wayland, etc.). The list + # below is a menu of extras — uncomment what you want and run + # `nomarchy-env-update`. home.packages = with pkgs; [ - # example: firefox thunderbird libreoffice + # --- Enabled by default --- + btop # Resource monitor (TUI) + fastfetch # System info at login + chromium # Secondary browser + + # --- Editors & dev --- + # vscode + # jetbrains.idea-community + # neovide + # zed-editor + # lazygit + # gh # GitHub CLI + # docker-compose + # postman + # dbeaver-bin + + # --- Productivity --- + # obsidian + # libreoffice + # thunderbird + # zathura # PDF viewer + # zotero + # xournalpp + + # --- Media --- + # vlc + # obs-studio + # gimp + # inkscape + # kdenlive + # spotify + # audacity + # yt-dlp + + # --- Comms --- + # discord + # telegram-desktop + # signal-desktop + # slack + # zoom-us + + # --- Security --- + # keepassxc + # bitwarden-desktop + # _1password-gui + + # --- Gaming --- + # steam + # lutris + # heroic + + # --- CLI / utilities --- + # ripgrep + # fd + # bat + # eza + # zoxide + # fzf + # httpie + # tldr ]; - # Add your personal home-manager configuration here + # Extra Home Manager modules go here (program configs, services, etc.). } EOF } @@ -510,6 +612,9 @@ finish() { echo " 3. Log in with username: $USERNAME" echo " 4. Your configuration is at /etc/nixos/" echo "" + echo "Tip: run 'nomarchy-themes-prebuild' once to pre-cache every theme" + echo " variant. Theme switches after that are instant (no rebuild)." + echo "" if nrun gum confirm "Reboot now?"; then reboot diff --git a/lib/default.nix b/lib/default.nix index c83a9e2..18c2feb 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -78,6 +78,20 @@ let else default; + # Map an icon-theme name (as declared in a palette's icons.theme file) to + # the nixpkgs attribute that ships it. Anything unknown falls back to + # yaru-theme so GTK still has a working default. + # + # When adding a palette that uses a new icon family, extend this mapping + # so `nomarchy-theme-set ` auto-installs the matching package. + iconThemePackage = { iconsTheme, pkgs }: + if lib.hasPrefix "Yaru" iconsTheme then pkgs.yaru-theme + else if lib.hasPrefix "Everforest" iconsTheme then pkgs.everforest-gtk-theme + else if lib.hasPrefix "Papirus" iconsTheme then pkgs.papirus-icon-theme + else if lib.hasPrefix "Adwaita" iconsTheme then pkgs.adwaita-icon-theme + else if lib.hasPrefix "breeze" iconsTheme || lib.hasPrefix "Breeze" iconsTheme then pkgs.kdePackages.breeze-icons + else pkgs.yaru-theme; + # Get list of available theme names themeNames = builtins.attrNames palettes; @@ -92,5 +106,6 @@ in { getColorScheme isThemeLightMode getIconsTheme + iconThemePackage themeNames; } diff --git a/themes/engine/scripts/nomarchy-theme-set b/themes/engine/scripts/nomarchy-theme-set index 21d94f8..36b22b5 100755 --- a/themes/engine/scripts/nomarchy-theme-set +++ b/themes/engine/scripts/nomarchy-theme-set @@ -51,4 +51,15 @@ nomarchy-env-update nomarchy-theme-set-templates +# Walker reads its CSS via @import of ~/.config/nomarchy/current/theme/apps/walker/style.css, +# and waybar's shared fallback style does the same with waybar.css. HM's sd-switch +# only restarts services whose unit *definition* changed, so when only the imported +# file's contents change, neither gets reloaded. Restart them explicitly. +command -v nomarchy-restart-walker >/dev/null 2>&1 && nomarchy-restart-walker || true +command -v nomarchy-restart-waybar >/dev/null 2>&1 && nomarchy-restart-waybar || true + +# Reload the wallpaper — its ExecStart path is stable (~/.config/nomarchy/current/background) +# so sd-switch does not detect a unit change when only the symlink target moves. +systemctl --user restart nomarchy-wallpaper.service 2>/dev/null || true + nomarchy-hook theme-set "$THEME_NAME" diff --git a/themes/engine/scripts/nomarchy-themes-prebuild b/themes/engine/scripts/nomarchy-themes-prebuild new file mode 100755 index 0000000..6ff391b --- /dev/null +++ b/themes/engine/scripts/nomarchy-themes-prebuild @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Pre-realise every theme's Home Manager generation into the Nix store so +# future `nomarchy-theme-set` swaps are cache hits — no Stylix rebuild, no +# downloads. Run once after install (the installer wires this up) and again +# after adding or updating palettes. + +set -e + +if [ -f "/etc/nixos/flake.nix" ]; then + REPO_DIR="/etc/nixos" +elif [ -f "/etc/nomarchy/flake.nix" ]; then + REPO_DIR="/etc/nomarchy" +else + echo "Error: Nomarchy flake repository not found in /etc/nixos or /etc/nomarchy." >&2 + exit 1 +fi + +echo "Pre-building every theme variant from $REPO_DIR#allThemeVariants..." +echo "This is a one-time cache warm-up. Subsequent theme switches will be instant." +nix build --no-link --print-out-paths \ + --extra-experimental-features "nix-command flakes" \ + "$REPO_DIR#allThemeVariants" + +echo "Theme variants cached. Theme switches now avoid rebuilds." diff --git a/themes/engine/stylix.nix b/themes/engine/stylix.nix index b2127d0..84cd213 100644 --- a/themes/engine/stylix.nix +++ b/themes/engine/stylix.nix @@ -92,11 +92,17 @@ in }; }; - # GTK Icon Theme configuration + # GTK Icon Theme configuration. The package is derived from the theme's + # declared icon family (palettes//icons.theme), so switching to a + # palette that needs e.g. Everforest icons automatically installs + # `everforest-gtk-variant` instead of sticking with `yaru-theme`. gtk = { enable = lib.mkDefault true; iconTheme = lib.mkDefault { - package = pkgs.yaru-theme; + package = nomarchyLib.iconThemePackage { + iconsTheme = config.nomarchy.iconsTheme; + inherit pkgs; + }; name = config.nomarchy.iconsTheme; }; };