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;
};
};