#+title: Droidnix: A Dendritic NixOS + Home Manager Configuration #+author: Henro Veijer #+options: toc:t num:nil htmlize:nil #+language: en #+html_head: #+HTML_HEAD: #+HTML_HEAD: * Shortcuts [[#introduction][Introduction]] [[#the-assets-folder][The Assets Folder]] [[#the-actual-code][The Actual Code]] --- * Introduction :intro: :PROPERTIES: :CUSTOM_ID: introduction :END: ** What is Droidnix Droidnix is a modular, declarative NixOS + Home Manager configuration system. It allows users to choose between =Hyprland= and =Mangowc= as their window manager, with shared and WM-specific configurations managed via Emacs Org and Nix Flakes. The project is designed for reproducibility, maintainability, and cross-machine compatibility. *** Installed components: **** Core **** Hyprland **** Mangowc *** Goals, project Structure, import hierarchy This project uses a **modular NixOS configuration** with **Hyprland** and **MangoWC** support, designed for **literate programming** and **cross-device reusability**. The Droidnix repository is organized into two main parts: 1. =.assets/=: Static, non-generated files (e.g., configs, scripts, themes). 2. Generated folders (=system=, =hyprland=, =mangowc=): NixOS and Home Manager configurations, generated from Org files. #+title: NixOS Configuration Structure * Root Level - =flake.nix= is the entry point and imports: - =generated/system/= - =generated/modules/desktop/= - Machine-specific configurations from =assets/machines/= * Generated Structure The =generated/= directory contains all generated configurations, divided into three main groups: =system=, =hyprland=, and =mangowc=. ** First Setup 1. Clone this repository. 2. Run the setup script: =./setup_droid=. 3. Edit =.assets/system/conf/base.conf= to choose your window manager (=wm = "hyprland"= or =wm = "mangowc"=). 4. Tangle this Org file to generate Nix configurations: =C-c C-v t= in Emacs or use this: =emacs README.org --batch -f org-babel-tangle && emacs --batch --eval "(setq org-html-htmlize-output-type nil)" README.org -f org-html-export-to-html= 5. Build and switch: =sudo nixos-rebuild switch --flake .#=. --- * The Assets Folder :assets: :PROPERTIES: :CUSTOM_ID: the-assets-folder :END: The =.assets/= folder contains all static files, such as configs, scripts, and themes. These files are not generated and can be edited directly. * The Actual Code :code: :PROPERTIES: :CUSTOM_ID: the-actual-code :END: This section contains the Org blocks for tangling Nix code into the generated folders. ** =flake.nix= The Nix flake definition for Droidnix. #+BEGIN_SRC nix :tangle flake.nix :noweb tangle :mkdirp yes :eval never-html { description = "Droidnix: A dendritic NixOS + Home Manager configuration"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; hyprland.url = "github:hyprwm/Hyprland"; flake-parts.url = "github:hercules-ci/flake-parts"; import-tree.url = "github:vic/import-tree"; stylix = { url = "github:nix-community/stylix"; inputs.nixpkgs.follows = "nixpkgs"; }; emacs-overlay = { url = "github:nix-community/emacs-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; zen-browser = { url = "github:youwen5/zen-browser-flake"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = inputs@{ flake-parts, nixpkgs, ... }: flake-parts.lib.mkFlake { inherit inputs; } { systems = [ "x86_64-linux" ]; flake = { nixosConfigurations.traveldroid = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; specialArgs = { inherit inputs; }; modules = [ ./generated/system/mysystem.nix ] ++ (inputs.import-tree ./generated/modules).imports ++ [ ./generated/hosts/traveldroid/traveldroid.nix ./generated/hosts/traveldroid/boot.nix ./generated/hosts/traveldroid/hardware-configuration.nix inputs.stylix.nixosModules.default inputs.home-manager.nixosModules.home-manager ]; }; }; }; } #+END_SRC ** =generated/system/mysystem.nix= This sets the networking. #+BEGIN_SRC nix :tangle generated/system/mysystem.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: { options.mySystem = lib.mkOption { type = lib.types.attrs; default = {}; description = "Root for custom mySystem options (placeholder)"; }; } #+END_SRC * Let's define the core of the system ** =generated/hosts/traveldroid/networking.nix= This sets the networking. #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/networking.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs,... }: let coreEnabled = config.mySystem.system.core.enable or false; in { options.mySystem.system.locale.enable = lib.mkEnableOption "Network settings"; config = lib.mkIf (coreEnabled || config.mySystem.system.locale.enable) { networking = { useDHCP = lib.mkDefault true; networkmanager.enable = true; networkmanager.wifi.backend = "iwd"; wireless.iwd.enable = true; wireless.userControlled.enable = true; firewall = { enable = true; # KDE Connect: discovery + encrypted connections allowedTCPPortRanges = [ { from = 1714; to = 1764; } ]; allowedUDPPortRanges = [ { from = 1714; to = 1764; } ]; }; }; # Install NetworkManager environment.systemPackages = with pkgs; [ networkmanager ]; }; } #+END_SRC ** =generated/hosts/traveldroid/services.nix= This sets the networking. #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/services.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let coreEnabled = config.mySystem.system.core.enable or false; in { options.mySystem.system.locale.enable = lib.mkEnableOption "Services settings (printing / audio)"; config = lib.mkIf (coreEnabled || config.mySystem.system.locale.enable) { # --- Services (Printing & Audio) --- services.printing.enable = true; services.pulseaudio.enable = false; security.rtkit.enable = true; services.pipewire = { enable = true; alsa.enable = true; alsa.support32Bit = true; pulse.enable = true; }; }; } #+END_SRC ** =generated/hosts/traveldroid/users/user.nix= This is the default user, just search and replace henrov another name if you want to change #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/users/user.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, inputs, ... }: let user = import ./henrov.nix; in { home-manager.users.${user.username} = { home.stateVersion = "25.11"; home.username = user.username; home.homeDirectory = user.homeDirectory; }; # Ensure the user is in the necessary groups users.users.${config.users.users.${user.username}.username} = { extraGroups = [ "wheel" "networkmanager" ]; }; } #+END_SRC ** =generated/hosts/traveldroid/users/henrov.nix= This is the default user, just search and replace henrov another name if you want to change #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/users/henrov.nix :noweb tangle :mkdirp yes :eval never-html { username = "henrov"; hashedPassword = "$6$ISAmsPLyFi7idYXr$VmZsq.zMsyh1irSkyDNqtorNXG0oEHbbMVqTii1t8bymvrQ5ZQmbdi4OiBNeNYe/huHGrojXM.3TST2fTLz0T."; homeDirectory = "/home/henrov"; stateVersion = "25.11"; locale = "nl_NL.UTF-8"; } #+END_SRC ** =generated/hosts/traveldroid/homebase.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/homebase.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let coreEnabled = config.mySystem.system.core.enable or false; in { options.mySystem.system.locale.enable = lib.mkEnableOption "Home-Manager settings"; config = lib.mkIf (coreEnabled || config.mySystem.system.locale.enable) { # --- Home Manager Base --- home-manager = { backupFileExtension = "backup"; users.henrov = { home.sessionVariables = { TERMINAL = "kitty"; EDITOR = "emacs"; BROWSER = "zen"; }; home.stateVersion = "25.11"; }; }; }; } #+END_SRC ** =generated/hosts/traveldroid/nix.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/nix.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let coreEnabled = config.mySystem.system.core.enable or false; in { # Top-level option for this module options.mySystem.system.locale.enable = lib.mkEnableOption "Enable Nix & Flake specific settings"; # Top-level container for all custom program configs (your myPrograms idea) options.myPrograms = lib.mkOption { type = lib.types.attrsOf lib.types.any; default = {}; description = "Container for all custom program configurations"; }; # Apply the configuration only if core or locale is enabled config = lib.mkIf (coreEnabled || config.mySystem.system.locale.enable) { nix.settings = { experimental-features = [ "nix-command" "flakes" ]; download-buffer-size = 536870912; # 512 MB cores = 2; max-jobs = 1; }; }; } #+END_SRC ** =generated/hosts/traveldroid/boot.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/boot.nix :noweb tangle :mkdirp yes :eval never-html { inputs, config, lib, pkgs, ... }: { boot.loader.grub = { enable = true; efiSupport = true; device = "nodev"; useOSProber = true; }; #boot.efi.canTouchEfiVariables = true; boot.kernelParams = [ "systemd.mask=dev-tpm0.device" "systemd.mask=dev-tpmrm0.device" ]; } #+END_SRC * First the nix-files that flake really needs and that do not fit wel in the hierarchical structure ** =generated/hosts/traveldroid/traveldroid.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/traveldroid.nix :noweb tangle :mkdirp yes :eval never-html { config, lib, ... }: { # Host-specific system configuration networking.hostName = "traveldroid"; system.stateVersion = "25.11"; # User-defined features mySystem.system.core.enable = true; # Hardware overrides hardware.nvidia.enabled = false; } #+END_SRC ** =generated/hosts/traveldroid/hardware-configuration.nix= 1. Boot into NixOS Live ISO or your installed system. 2. Open a terminal. 3. Run: sudo nixos-generate-config --root /mnt (Omit --root /mnt if already running NixOS.) #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/hardware-configuration.nix :noweb tangle :mkdirp yes :eval never-html { hostname, pkgs, lib, modulesPath, user, config, ... }: { imports = [ # (modulesPath + "/installer/scan/not-detected.nix") #../../hardware/hardware.nix ]; boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; fileSystems."/" = { device = "/dev/disk/by-uuid/69433a14-fbaf-401b-af85-cd1bbf02b4e2"; fsType = "ext4"; }; fileSystems."/boot" = { device = "/dev/disk/by-uuid/811D-0676"; fsType = "vfat"; options = [ "fmask=0077" "dmask=0077" ]; }; swapDevices = [ { device = "/dev/disk/by-uuid/b6c557c2-7682-460b-a5e7-8f6f2f429a3a"; } ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } #+END_SRC ** =generated/hosts/traveldroid/dbus.nix= This sets the dbus implementation #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/dbus.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: { services.dbus = lib.mkForce { enable = true; # Force this to be true }; # Configure dbus-broker via its configuration file environment.etc."dbus-broker/launch.conf".text = '' [General] LogLevel=warning MaxConnectionsPerUser=2048 ''; } #+END_SRC ** =generated/hosts/traveldroid/bluetooth.nix= This sets the bluetooth implementation #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/bluetooth.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { # Enable Bluetooth hardware and daemon hardware.bluetooth = { enable = true; powerOnBoot = true; packages = with pkgs; [ bluez ]; }; # Enable Bluetooth audio support in PipeWire services.pipewire = { config.pulse = { bluez5.enable = true; }; }; # Optional: Additional Bluetooth settings hardware.bluetooth.extraConfig = '' AutoEnable=true DiscoverableTimeout=0 PairableTimeout=0 ''; # Install a graphical Bluetooth manager (optional) environment.systemPackages = with pkgs; [ blueman ]; } #+END_SRC ** =generated/hosts/traveldroid/xdg.nix= This sets the XDG implementation #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/xdg.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { xdg.portal = { enable = true; config.system.default = [ "hyprland" "gtk" ]; }; } #+END_SRC ** =generated/modules/desktop/stylix.nix= This sets the stylix implementation #+BEGIN_SRC nix :tangle generated/modules/desktop/stylix.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs, flakeRoot, ... }: let # --- Program definition --- programName = "stylix"; # Assets (theme + wallpaper) programAssets = "${flakeRoot}/assets/system/theming/${programName}"; programFiles = if builtins.pathExists programAssets then builtins.readDir programAssets else {}; files = lib.genAttrs (builtins.attrNames programFiles) (name: { src = "${programAssets}/${name}"; }); # Enable toggle (must match option) enableProgram = config.enableStylix or true; # Resolve user safely (outside mkIf) user = config.defaultUser or "henrov"; # --- Stylix configuration (self-contained) --- stylixCfg = { enable = true; base16Scheme = "${flakeRoot}/assets/system/theming/stylix/catppuccin-mocha.yaml"; image = "${flakeRoot}/assets/hyprland/wallpaperstuff/pictures/wall1.jpg"; polarity = "dark"; cursor = { package = pkgs.phinger-cursors; name = "phinger-cursors-light"; size = 24; }; fonts = { monospace = { package = pkgs.nerd-fonts.fira-code; name = "Fira Code Nerd Font"; }; sansSerif = { package = pkgs.lato; name = "Lato"; }; }; icons = { enable = true; package = pkgs.papirus-icon-theme; dark = "Papirus-Dark"; light = "Papirus-Light"; }; }; in { # --- Option --- options.enableStylix = lib.mkEnableOption "Enable Stylix system theming"; # --- Config --- config = lib.mkIf enableProgram { # --- Dendritic app definition --- myApps.${programName} = { enable = true; assetsDir = programAssets; files = files; inherit user; theme = "catppuccin-mocha"; polarity = "dark"; }; # --- Stylix theming --- stylix = stylixCfg; # --- Optional: wallpaper helper (kept dendritic) --- myApps.wallpaper = { enable = true; packages = [ "feh" "st" ]; }; # --- Cursor environment variables --- home-manager.users.${user}.home.sessionVariables = { XCURSOR_THEME = stylixCfg.cursor.name; XCURSOR_SIZE = toString stylixCfg.cursor.size; HYPRCURSOR_THEME = stylixCfg.cursor.name; HYPRCURSOR_SIZE = toString stylixCfg.cursor.size; }; }; } #+END_SRC ** =generated/hosts/traveldroid/terminal.nix= Sets theming for the terminal #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/terminal.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { # (NVF = Neovim/terminal flavor) stylix.targets.nvf.enable = true; # feh wallpaper integration stylix.targets.feh.enable = true; } #+END_SRC ** =generated/modules/desktop/rotating_wallpaper.nix= rotating_wallpaper.nix installs wpaperd and deploys your wallpaper files from the repo (./assets/hyprland/wallpaperstuff/) into ~/Droidnix/wallpaperstuff/. You can edit assets/hyprland/wallpaperstuff/wallpaper.toml to change settings Finally, it creates a systemd user service (wpaperd.service) that automatically starts wpaperd at login and keeps it running, using your override config so wallpapers rotate according to your settings. # #+BEGIN_SRC nix :tangle generated/modules/desktop/rotating_wallpaper.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: { flake.nixosModules.rotating-wallpaper = { config, pkgs, lib, ... }: let wallpaperConf = ../../../assets/hyprland/wallpaperstuff/wallpaper.toml; in { options.mySystem.desktop.wallpaper.enable = lib.mkEnableOption "Enable rotating wallpaper via wpaperd"; config = lib.mkIf (config.mySystem.desktop.wallpaper.enable or false) { # Home Manager context home-manager.users.henrov = { home.packages = [ pkgs.wpaperd ]; home.file.".config/wpaperd/wallpaper.toml".source = wallpaperConf; systemd.user.services.wpaperd = { description = "wpaperd wallpaper daemon"; wantedBy = [ "default.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.wpaperd}/bin/wpaperd --config ~/.config/wpaperd/wallpaper.toml"; Restart = "on-failure"; RestartSec = 1; }; }; }; }; }; } # #+END_SRC ** =generated/modules/desktop/hyprland.nix= Setting up Hyprland #+BEGIN_SRC nix :tangle generated/modules/desktop/hyprland.nix :noweb tangle :mkdirp yes :eval never-html { lib, pkgs, flakeRoot, ... }: let # --- Define user locally --- username = "henrov"; # --- Hyprland conf directory --- hyprConfDir = "${flakeRoot}/assets/hyprland/conf/hypr"; # --- Read files --- hyprlandFiles = builtins.attrNames (builtins.readDir hyprConfDir); # --- Exclude main hyprland.conf from automatic symlinks --- otherHyprlandFiles = lib.filter (name: name != "hyprland.conf") hyprlandFiles; # --- Generate xdg.configFile entries for the other files --- otherConfigs = lib.genAttrs otherHyprlandFiles (name: { target = "hypr/${name}"; source = "${hyprConfDir}/${name}"; }); # --- Add main hyprland.conf separately --- hyprlandConf = { "hypr/hyprland.conf".text = builtins.readFile "${hyprConfDir}/hyprland.conf"; "hypr/.keep".text = ""; }; in { flake.nixosModules.hyprland = { config, pkgs, lib, ... }: { options.mySystem.desktop.hyprland.enable = lib.mkEnableOption "Enable Hyprland Desktop"; config = lib.mkIf (config.mySystem.desktop.hyprland.enable or false) { programs.hyprland.enable = true; home-manager.users.${username} = { home.stateVersion = "25.11"; home.username = username; home.homeDirectory = "/home/${username}"; wayland.windowManager.hyprland = { enable = true; settings.general."col.active_border" = lib.mkForce "0xff97cbcd 0xff89b4fa"; }; xdg.configFile = otherConfigs // hyprlandConf; }; }; }; } #+END_SRC ** =generated/modules/apps/zenbrowser.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/modules/apps/zenbrowser.nix :noweb tangle :mkdirp yes :eval never-html # ./generated/modules/apps/zenbrowser.nix { lib, pkgs, ... }: let username = "henrov"; # vervang door je echte gebruikersnaam in { flake.nixosModules.zenbrowser = { config, pkgs, lib, ... }: { options.mySystem.apps.zenbrowser.enable = lib.mkEnableOption "Enable Zen Browser"; config = lib.mkIf (config.mySystem.apps.zenbrowser.enable or false) { # --- Home Manager gebruiker --- home-manager.users.${username} = { home.stateVersion = "25.11"; home.username = username; home.homeDirectory = "/home/${username}"; # --- Thunar en plugins --- home.packages = with pkgs; [ zen-browser ]; }; }; }; } #+END_SRC ** =generated/modules/apps/packages.nix= This will import all packages listed in ./assets/system/apps/packages.conf #+BEGIN_SRC nix :tangle generated/modules/apps/packages.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: let # --- Path naar je packages.conf, relatief aan dit bestand --- packagesConfPath = ./assets/system/apps/packages.conf; # --- Lees en split --- raw = builtins.readFile packagesConfPath; rawLines = lib.splitString "\n" raw; _guard = assert !(builtins.stringLength raw > 1 && builtins.length rawLines == builtins.stringLength raw); true; cleanLine = line: let noCR = lib.replaceStrings [ "\r" ] [ "" ] line; noComment = lib.head (lib.splitString "#" noCR); in lib.strings.trim noComment; entries = builtins.filter (l: l != "") (map cleanLine rawLines); in { # --- Flake NixOS module export --- flake.nixosModules.packages = { config, pkgs, lib, ... }: let # Resolve packages via pkgs resolvePkg = name: let parts = lib.splitString "." name; found = lib.attrByPath parts null pkgs; in if found == null then throw '' packages.nix: package not found in pkgs Token : ${builtins.toJSON name} packages.conf : ${toString packagesConfPath} '' else found; packages = builtins.seq _guard (map resolvePkg entries); in { options.mySystem.system.packages.enable = lib.mkEnableOption "Enable packages from packages.conf"; config = lib.mkIf (config.mySystem.system.packages.enable or false) { environment.systemPackages = packages; }; }; } #+END_SRC ** =generated/modules/apps/flatpaks.nix= This will import all packages listed in ./assets/system/apps/flatpaks.conf #+BEGIN_SRC nix :tangle generated/modules/apps/flatpaks.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: let moduleName = "install-flatpaks"; # --- Relatief pad binnen deze module (geen flakeRoot) --- flatpakConfPath = ./assets/system/apps/flatpaks.conf; # --- Lees en split het bestand --- raw = builtins.readFile flatpakConfPath; rawLines = lib.splitString "\n" raw; # --- Guard: check dat we niet per karakter hebben gesplit --- _guard = assert !(builtins.stringLength raw > 1 && builtins.length rawLines == builtins.stringLength raw); true; # --- Cleanup per regel --- cleanLine = line: let noCR = lib.replaceStrings [ "\r" ] [ "" ] line; noInlineComment = lib.head (lib.splitString "#" noCR); in lib.strings.trim noInlineComment; entries = builtins.filter (l: l != "") (map cleanLine rawLines); # --- Validatie: min 2 dots (reverse-DNS stijl) --- dotCount = s: builtins.length (lib.splitString "." s) - 1; isValidId = s: (dotCount s) >= 2; _validate = builtins.seq _guard ( builtins.map (id: if isValidId id then true else throw '' ${moduleName}: invalid Flatpak ID in flatpaks.conf (needs reverse-DNS with at least 2 dots) Token : ${builtins.toJSON id} flatpaks.conf : ${toString flatpakConfPath} Fix: remove stray tokens or comment them out with '#'. '' ) entries ); flatpakApps = builtins.seq _validate entries; in { # --- Export as NixOS module via flake.nixosModules --- flake.nixosModules.flatpaks = { config, pkgs, lib, ... }: let syncFlatpaks = pkgs.writeShellScript "sync-flatpaks" '' set -euo pipefail CONF="/etc/flatpak/flatpaks.conf" if [[ -f "$CONF" ]]; then echo "flatpak-sync: using $CONF" else echo "flatpak-sync: WARNING: $CONF not found, using embedded list" fi if ! flatpak remotes --system --columns=name | grep -qx flathub; then flatpak remote-add --system --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo fi desired_apps=( ${lib.concatStringsSep " " (map (a: ''"${a}"'') flatpakApps)} ) for app in $desired_apps; do if ! flatpak info --system "$app" >/dev/null 2>&1; then flatpak install --system -y --noninteractive flathub "$app" fi done ''; in { options.mySystem.system.flatpaks.enable = lib.mkEnableOption "Enable automatic Flatpak installation"; config = lib.mkIf (config.mySystem.system.flatpaks.enable or false) { services.flatpak.enable = true; xdg.portal.enable = true; # Deploy de conf voor runtime/debug environment.etc."flatpak/flatpaks.conf".source = lib.mkForce flatpakConfPath; # Systemd service voor automatische installatie systemd.services.flatpak-sync = { description = "Install Flatpak apps listed in flatpaks.conf"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; ExecStart = syncFlatpaks; }; restartTriggers = [ flatpakConfPath ]; path = [ pkgs.flatpak pkgs.coreutils pkgs.gnugrep pkgs.gnused ]; }; }; }; } #+END_SRC ** =generated/hosts/traveldroid/gtk.nix= Setting up GTK #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/gtk.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, user, ... }: { environment.systemPackages = with pkgs; [ gtk3 # GTK target gtk4 # GTK target ]; # Stylix GTK target stylix.targets.gtk.enable = true; home-manager.users.${user.username} = { gtk = { enable = true; theme = { name = "Catppuccin-Mocha-Standard-Blue-Dark"; package = pkgs.magnetic-catppuccin-gtk; }; iconTheme = { name = "Papirus-Dark"; package = pkgs.papirus-icon-theme; }; gtk3.extraConfig = { gtk-application-prefer-dark-theme = 1; }; gtk4.extraConfig = { gtk-application-prefer-dark-theme = 1; }; }; }; } #+END_SRC ** =generated/modules/desktop/fonts.nix= This file installs and configures fonts #+BEGIN_SRC nix :tangle generated/modules/desktop/fonts.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: { flake.nixosModules.fonts = { config, pkgs, lib, ... }: { options.mySystem.desktop.fonts.enable = lib.mkEnableOption "Enable system fonts"; config = lib.mkIf (config.mySystem.desktop.fonts.enable or false) { fonts.packages = with pkgs; [ nerd-fonts.iosevka nerd-fonts.fira-code ]; }; }; } #+END_SRC ** =generated/modules/desktop/eww.nix= This file installs and configures eww #+BEGIN_SRC nix :tangle generated/modules/desktop/eww.nix :noweb tangle :mkdirp yes :eval never-html { lib, pkgs, flakeRoot, ... }: let # --- Define user locally --- username = "henrov"; # --- Eww config directory in flake --- ewwAssetsDir = "${flakeRoot}/assets/system/conf/eww"; # --- Read all files in ewwAssetsDir dynamically --- ewwFiles = builtins.attrNames (builtins.readDir ewwAssetsDir); # --- Generate xdg.configFile entries for all files --- ewwConfigs = lib.genAttrs ewwFiles (name: { text = builtins.readFile "${ewwAssetsDir}/${name}"; }); # --- Full config directory path in user's config home --- ewwConfigDir = "/home/${username}/.config/eww"; in { flake.nixosModules.eww = { config, pkgs, lib, ... }: { options.mySystem.apps.eww.enable = lib.mkEnableOption "Enable Eww widgets"; config = lib.mkIf (config.mySystem.apps.eww.enable or false) { mySystem = { apps.wallpaper = { enable = true; packages = [ "eww" ]; # symbolic, actual package below }; }; # --- Home Manager user config --- home-manager.users.${username} = { home.stateVersion = "25.11"; home.username = username; home.homeDirectory = "/home/${username}"; # Deploy eww configs home.file."${ewwConfigDir}" = { source = ewwAssetsDir; recursive = true; }; # Session variables home.sessionVariables = { EWW_BIN = "${pkgs.eww}/bin/eww"; }; # Wayland/Hyprland startup hooks wayland.windowManager.hyprland.settings = lib.mkForce { exec-once = [ "eww daemon" ]; exec = [ "eww open-many ${ewwConfigDir}/widgets" ]; }; }; }; }; } #+END_SRC ** =generated/modules/desktop/waybar.nix= This file installs and configures waybar #+BEGIN_SRC nix :tangle generated/modules/desktop/waybar.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: let username = "henrov"; waybarAssets = ../../../assets/system/conf/waybar; waybarFiles = builtins.readDir waybarAssets; waybarConfs = lib.genAttrs (builtins.attrNames waybarFiles) (name: { src = "${waybarAssets}/${name}"; }); enableWaybar = true; in { # Declare a top-level option options.myApps = lib.mkOption { type = lib.types.attrsOf lib.types.any; default = {}; description = "Top-level collection of custom apps"; }; options.enableWaybar = lib.mkEnableOption "Enable Waybar status bar"; # Everything goes under config safely config = lib.mkIf enableWaybar { myApps = { waybar = { enable = true; user = username; assetsDir = waybarAssets; files = waybarConfs; }; }; }; } #+END_SRC ** =generated/hosts/traveldroid/login-tuigreeter.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/login-tuigreeter.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, user, ... } : { environment.systemPackages = with pkgs; [ tuigreet ]; services.greetd = { enable = true; settings = { default_session = { command = pkgs.lib.mkForce "${pkgs.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'"; }; }; }; } #+END_SRC ** =generated/modules/desktop/wayland.nix= This file sets up wayland #+BEGIN_SRC nix :tangle generated/modules/desktop/wayland.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let # --- Program definition --- programName = "wayland"; # Assets (optional, kept for consistency with template) programAssets = ../../../assets/system/conf/${programName}; programFiles = if builtins.pathExists programAssets then builtins.readDir programAssets else {}; files = lib.genAttrs (builtins.attrNames programFiles) (name: { src = "${programAssets}/${name}"; }); # Enable toggle (must match option name) enableProgram = config.enableWayland or true; # Resolve user safely (outside mkIf) user = config.defaultUser or "henrov"; in { # --- Option --- options.enableWayland = lib.mkEnableOption "Enable Wayland + portals"; # --- Config --- config = lib.mkIf enableProgram { # --- Dendritic app definition --- myApps.${programName} = { enable = true; assetsDir = programAssets; files = files; inherit user; # Wayland-specific metadata portals = [ "hyprland" ]; }; # --- Actual system wiring --- home-manager.users.${user} = { xdg.portal = { enable = true; # pkgs is unavoidable here (real package dependency) extraPortals = [ config.pkgs.xdg-desktop-portal-hyprland ]; config.hyprland = { "org.freedesktop.impl.portal.Screencast" = [ "hyprland" ]; }; }; home.packages = [ config.pkgs.uwsm ]; }; }; } #+END_SRC ** =generated/modules/apps/thunar.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/modules/apps/thunar.nix :noweb tangle :mkdirp yes :eval never-html { lib, pkgs, ... }: let username = "henrov"; # vervang door je echte gebruikersnaam in { flake.nixosModules.thunar = { config, pkgs, lib, ... }: { options.mySystem.apps.thunar.enable = lib.mkEnableOption "Enable Thunar file manager"; config = lib.mkIf (config.mySystem.apps.thunar.enable or false) { # --- Home Manager gebruiker --- home-manager.users.${username} = { home.stateVersion = "25.11"; home.username = username; home.homeDirectory = "/home/${username}"; # --- Thunar en plugins --- home.packages = with pkgs; [ thunar thunar-volman thunar-archive-plugin thunar-media-tags-plugin tumbler ffmpegthumbnailer gvfs xdg-utils ]; # --- Default file manager --- xdg.mimeApps = { defaultApplications = { "inode/directory" = "Thunar.desktop"; }; }; }; }; }; } #+END_SRC ** =generated/modules/terminals/kitty.nix= This file sets up Kitty terminal #+BEGIN_SRC nix :tangle generated/modules/terminals/kitty.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let # --- Program definition --- programName = "kitty"; # Assets directory (relative, self-contained) programAssets = ../../../assets/system/conf/${programName}; # Read all files in assets dir programFiles = builtins.readDir programAssets; # Map files → attrset files = lib.genAttrs (builtins.attrNames programFiles) (name: { src = "${programAssets}/${name}"; }); # Enable toggle (safe: defined before config) enableProgram = config.enableKitty or true; # Resolve user safely (top-level, not inside mkIf) user = config.defaultUser or "henrov"; in { # --- Option --- options.enableKitty = lib.mkEnableOption "Enable kitty terminal"; # --- Config --- config = lib.mkIf enableProgram { myApps.${programName} = { enable = true; assetsDir = programAssets; files = files; inherit user; # Program-specific metadata theme = "catppuccin-mocha"; }; # Actual system wiring (kept minimal + scoped) home-manager.users.${user} = { programs.kitty.enable = true; xdg.configFile = lib.mapAttrs' (name: value: { name = "kitty/${name}"; value.source = value.src; }) files; }; }; } #+END_SRC ** =generated/modules/terminals/starship.nix= This file sets up starship prompt #+BEGIN_SRC nix :tangle generated/modules/terminals/starship.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: let # Path to your Starship config inside the flake starshipAssets = ../../../assets/system/conf/starship.toml; # Read and parse the TOML file as a symbolic value starshipConfig = lib.importTOML starshipAssets; # Toggle on/off enableStarship = true; in { # Declare a top-level module option options.starship = { enable = lib.mkEnableOption "Enable Starship prompt"; configFiles = lib.mkOption { type = lib.types.attrsOf lib.types.any; default = {}; description = "Symbolic Starship configuration files"; }; }; # Populate the option safely config = lib.mkIf enableStarship { starship.enable = true; starship.configFiles = { "starship.toml" = starshipConfig; assetsDir = ../../../assets/system/conf; }; }; } #+END_SRC ** =generated/modules/terminals/zsh.nix= This sets up the zsh in the terminal #+BEGIN_SRC nix :tangle generated/modules/terminals/zsh.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: let # --- Program-specific paths/assets --- programName = "zsh"; programAssets = ../../../assets/system/conf/${programName}; programFiles = builtins.readDir programAssets; files = lib.genAttrs (builtins.attrNames programFiles) (name: { src = "${programAssets}/${name}"; }); in { # Top-level toggle for this program options.enableZsh = lib.mkEnableOption "Enable Zsh terminal with Oh-My-Zsh"; # Wrap everything in config if enabled config = { config, ... }: let # Enable flag now safely references the toggle option enableProgram = config.enableZsh or false; # Safe reference to defaultUser inside mkIf username = config.defaultUser or "henrov"; in lib.mkIf enableProgram { myApps = { zsh = { enable = true; assetsDir = programAssets; files = files; user = username; # Zsh-specific settings ohMyZsh = { enable = true; theme = "catppuccin-mocha"; plugins = [ "git" "docker" "direnv" "zsh-autosuggestions" "zsh-completions" "zsh-history-substring-search" # zsh-syntax-highlighting is sourced in initExtra ]; }; initExtra = '' # Catppuccin Mocha colors local mocha_base="#1E1E2E" local mocha_surface0="#313244" local mocha_text="#CDD6F4" local mocha_lavender="#B4BEFE" local mocha_blue="#89B4FA" local mocha_sapphire="#74C7EC" local mocha_teal="#94D2D5" local mocha_green="#A6E3A1" local mocha_yellow="#F9E2AF" local mocha_peach="#FAB387" local mocha_maroon="#EBA0AC" local mocha_red="#F38BA8" local mocha_mauve="#CBA6F7" local mocha_pink="#F5E2C7" local mocha_flamingo="#F2CDCD" local mocha_rosewater="#F5E0DC" # Prompt PROMPT='%{$fg[$mocha_blue]%}%n%{$reset_color%}@%{$fg[$mocha_peach]%}%m%{$reset_color%} %{$fg[$mocha_lavender]%}%~%{$reset_color%} %{$fg[$mocha_red]%}$%{$reset_color%} ' RPROMPT='%{$fg[$mocha_green]%}%T%{$reset_color%}' # Source zsh-syntax-highlighting if present if [ -f ${files."zsh-syntax-highlighting".src} ]; then source ${files."zsh-syntax-highlighting".src} fi ''; }; }; }; }#+END_SRC ** =generated/modules/apps/emacs/emacs.nix= This sets up the emacs terminal #+BEGIN_SRC nix :tangle generated/modules/apps/emacs/emacs.nix :noweb tangle :mkdirp yes :eval never-html { lib, ... }: { flake.nixosModules.emacs = { config, pkgs, lib, ... }: { # Optie om de module aan/uit te zetten options.mySystem.system.emacs.enable = lib.mkEnableOption "Enable Emacs config"; config = lib.mkIf (config.mySystem.system.emacs.enable or false) { # System packages (optioneel) environment.systemPackages = with pkgs; [ # Voeg systeem-brede packages toe als je wilt ]; # Home Manager configuratie home-manager.users.henrov = { programs.emacs = { enable = true; package = pkgs.emacs-pgtk.override { withTreeSitter = true; }; extraPackages = epkgs: with epkgs; [ # Tree-sitter and language support manualPackages.treesit-grammars.with-all-grammars rust-mode rustic nix-mode hcl-mode # UI/UX and navigation nerd-icons doom-modeline diminish eldoc eldoc-box pulsar which-key avy consult vertico marginalia crux shell-pop # Completion and snippets nerd-icons-corfu corfu cape orderless yasnippet yasnippet-snippets # Utilities and tools rg exec-path-from-shell eat f gptel nixpkgs-fmt envrc # Theming catppuccin-theme # Git magit # Editing and workflow expreg vundo puni # Error and side panel support sideline sideline-flymake sideline-eglot ]; }; home.sessionVariables = { EDITOR = "emacs"; XDG_SCREENSHOTS_DIR = "~/screenshots"; }; }; }; }; } #+END_SRC ** =generated/modules/apps/emacs/early-init.el= This helps set up the emacs terminal #+BEGIN_SRC nix :tangle generated/modules/apps/emacs/early-init.el :noweb tangle :mkdirp yes :eval never-html ;;; package --- early init -*- lexical-binding: t -*- ;;; Commentary: ;;; Prevents white flash and better Emacs defaults ;;; Code: (set-language-environment "UTF-8") (setq-default default-frame-alist '((background-color . "#1e1e2e") (bottom-divider-width . 1) ; Thin horizontal window divider (foreground-color . "#bac2de") ; Default foreground color (fullscreen . maximized) ; Maximize the window by default (horizontal-scroll-bars . nil) ; No horizontal scroll-bars (left-fringe . 8) ; Thin left fringe (menu-bar-lines . 0) ; No menu bar (right-divider-width . 1) ; Thin vertical window divider (right-fringe . 8) ; Thin right fringe (tool-bar-lines . 0) ; No tool bar (undecorated . t) ; Remove extraneous X decorations (vertical-scroll-bars . nil)) ; No vertical scroll-bars user-full-name "Henrov henrov" ; ME! ;; memory configuration ;; Higher garbage collection threshold, prevents frequent gc locks, reset later gc-cons-threshold most-positive-fixnum ;; Ignore warnings for (obsolete) elisp compilations byte-compile-warnings '(not obsolete) ;; And other log types completely warning-suppress-log-types '((comp) (bytecomp)) ;; Large files are okay in the new millenium. large-file-warning-threshold 100000000 ;; dont show garbage collection messages at startup, will reset later garbage-collection-messages nil ;; native compilation package-native-compile t native-comp-warning-on-missing-source nil native-comp-async-report-warnings-errors 'silent ;; Read more based on system pipe capacity read-process-output-max (max (* 10240 10240) read-process-output-max) ;; scroll configuration scroll-margin 0 ; Lets scroll to the end of the margin scroll-conservatively 100000 ; Never recenter the window scroll-preserve-screen-position 1 ; Scrolling back and forth ;; frame config ;; Improve emacs startup time by not resizing to adjust for custom settings frame-inhibit-implied-resize t ;; Dont resize based on character height / width but to exact pixels frame-resize-pixelwise t ;; backups & files backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter backup-by-copying t ; Don't clobber symlinks create-lockfiles nil ; Don't have temp files delete-old-versions t ; Cleanup automatically kept-new-versions 6 ; Update every few times kept-old-versions 2 ; And cleanup even more version-control t ; Version them backups delete-by-moving-to-trash t ; Dont delete, send to trash instead ;; startup inhibit-startup-screen t ; I have already done the tutorial. Twice inhibit-startup-message t ; I know I am ready inhibit-startup-echo-area-message t ; Yep, still know it initial-scratch-message nil ; I know it is the scratch buffer! initial-buffer-choice nil inhibit-startup-buffer-menu t inhibit-x-resources t initial-major-mode 'fundamental-mode pgtk-wait-for-event-timeout 0.001 ; faster child frames ad-redefinition-action 'accept ; dont care about legacy things being redefined inhibit-compacting-font-caches t ;; tabs tab-width 4 ; Always tab 4 spaces. indent-tabs-mode nil ; Never use actual tabs. ;; rendering cursor-in-non-selected-windows nil ; dont render cursors other windows ;; packages use-package-always-defer t load-prefer-newer t default-input-method nil use-dialog-box nil use-file-dialog nil use-package-expand-minimally t package-enable-at-startup nil use-package-enable-imenu-support t auto-mode-case-fold nil ; No second pass of case-insensitive search over auto-mode-alist. package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") ("melpa-stable" . "https://stable.melpa.org/packages/")) package-archive-priorities '(("gnu" . 99) ("nongnu" . 80) ("melpa" . 70) ("melpa-stable" . 50)) ) ;;; early-init.el ends here #+END_SRC ** =generated/modules/apps/emacs/init.el= This helps set up the emacs terminal #+BEGIN_SRC nix :tangle generated/modules/apps/emacs/init.el :noweb tangle :mkdirp yes :eval never-html ;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*- ;;; Commentary: ;;; Simple Emacs setup I carry everywhere ;;; Code: (setq custom-file (locate-user-emacs-file "custom.el")) (load custom-file 'noerror) ;; no error on missing custom file (require 'package) (package-initialize) (defun reset-custom-vars () "Resets the custom variables that were set to crazy numbers" (setopt gc-cons-threshold (* 1024 1024 100)) (setopt garbage-collection-messages t)) (use-package emacs :custom (native-comp-async-query-on-exit t) (read-answer-short t) (use-short-answers t) (enable-recursive-minibuffers t) (which-func-update-delay 1.0) (visible-bell nil) (custom-buffer-done-kill t) (whitespace-line-column nil) (x-underline-at-descent-line t) (imenu-auto-rescan t) (uniquify-buffer-name-style 'forward) (confirm-nonexistent-file-or-buffer nil) (create-lockfiles nil) (make-backup-files nil) (kill-do-not-save-duplicates t) (sentence-end-double-space nil) (treesit-enabled-modes t) :init ;; base visual (menu-bar-mode -1) ;; no menu bar (toggle-scroll-bar -1) ;; no scroll bar (tool-bar-mode -1) ;; no tool bar either (blink-cursor-mode -1) ;; stop blinking ;; font of the century (set-frame-font "Aporetic Sans Mono 12" nil t) :bind (("C-" . pixel-scroll-precision) ; dont zoom in please, just scroll ("C-" . pixel-scroll-precision) ; dont zoom in either, just scroll ("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask :hook (text-mode . delete-trailing-whitespace-mode) (prog-mode . delete-trailing-whitespace-mode) (after-init . global-display-line-numbers-mode) ;; always show line numbers (after-init . column-number-mode) ;; column number in the mode line (after-init . size-indication-mode) ;; file size in the mode line (after-init . pixel-scroll-precision-mode) ;; smooth mouse scroll (after-init . electric-pair-mode) ;; i mean ... parens should auto create (after-init . reset-custom-vars) ) (use-package autorevert :ensure nil :custom (auto-revert-interval 3) (auto-revert-remote-files nil) (auto-revert-use-notify t) (auto-revert-avoid-polling nil) (auto-revert-verbose t) :hook (after-init . global-auto-revert-mode)) (use-package recentf :ensure nil :commands (recentf-mode recentf-cleanup) :hook (after-init . recentf-mode) :custom (recentf-auto-cleanup 'never) (recentf-exclude (list "\\.tar$" "\\.tbz2$" "\\.tbz$" "\\.tgz$" "\\.bz2$" "\\.bz$" "\\.gz$" "\\.gzip$" "\\.xz$" "\\.zip$" "\\.7z$" "\\.rar$" "COMMIT_EDITMSG\\'" "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$" "-autoloads\\.el$" "autoload\\.el$")) :config ;; A cleanup depth of -90 ensures that `recentf-cleanup' runs before ;; `recentf-save-list', allowing stale entries to be removed before the list ;; is saved by `recentf-save-list', which is automatically added to ;; `kill-emacs-hook' by `recentf-mode'. (add-hook 'kill-emacs-hook #'recentf-cleanup -90)) (use-package savehist :ensure nil :commands (savehist-mode savehist-save) :hook (after-init . savehist-mode) :custom (savehist-autosave-interval 600) (savehist-additional-variables '(kill-ring ; clipboard register-alist ; macros mark-ring global-mark-ring ; marks search-ring regexp-search-ring))) (use-package hl-line :ensure nil :custom (hl-line-sticky-flag nil) (global-hl-line-sticky-flag nil) :hook (after-init . global-hl-line-mode)) (use-package saveplace :ensure nil :commands (save-place-mode save-place-local-mode) :hook (after-init . save-place-mode) :custom (save-place-limit 400)) (use-package nerd-icons :custom ;; disable bright icon colors (nerd-icons-color-icons nil))hells.nix (use-package doom-modeline :custom (inhibit-compacting-font-caches t) ;; speed (doom-modeline-buffer-file-name-style 'relative-from-project) (doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you (doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway (doom-modeline-buffer-state-icon nil) ;; the filename already shows me (doom-modeline-lsp nil) ;; lsp state is too distracting, too often :hook (after-init . doom-modeline-mode)) (load-theme 'catppuccin :no-confirm) (use-package diminish :demand t) ;; declutter the modeline (use-package eldoc :diminish eldoc-mode :custom (eldoc-echo-area-use-multiline-p nil)) ;; docs for everything (use-package eldoc-box :defer t :config (set-face-background 'eldoc-box-border (catppuccin-color 'green)) (set-face-background 'eldoc-box-body (catppuccin-color 'base)) :bind (("M-h" . eldoc-box-help-at-point))) (use-package pulsar :commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry :init (defface pulsar-catppuccin `((default :extend t) (((class color) (min-colors 88) (background light)) :background ,(catppuccin-color 'sapphire)) (((class color) (min-colors 88) (background dark)) :background ,(catppuccin-color 'sapphire)) (t :inverse-video t)) "Alternative nord face for `pulsar-face'." :group 'pulsar-faces) :custom (pulsar-face 'pulsar-catppuccin) :hook (after-init . pulsar-global-mode)) (use-package which-key :commands which-key-mode :diminish which-key-mode :hook (after-init . which-key-mode)) (use-package expreg :bind ("M-m" . expreg-expand)) (use-package vundo) ;; undo tree ;; better structured editing (use-package puni :commands puni-global-mode :hook (after-init . puni-global-mode)) (use-package avy :bind ("M-i" . avy-goto-char-2) :custom (avy-background t)) (use-package consult :bind ("C-x b" . consult-buffer) ;; orig. switch-to-buffer ("M-y" . consult-yank-pop) ;; orig. yank-pop ("M-g M-g" . consult-goto-line) ;; orig. goto-line ("M-g i" . consult-imenu) ;; consult version is interactive ("M-g r" . consult-ripgrep) ;; find in project also works :custom (consult-narrow-key "<")) (use-package vertico :commands vertico-mode :custom (read-file-name-completion-ignore-case t) (read-buffer-completion-ignore-case t) (completion-ignore-case t) (enable-recursive-minibuffers t) (minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) :init (vertico-mode) :hook (minibuffer-setup-hook . cursor-intangible-mode)) (use-package marginalia :commands marginalia-mode :hook (after-init . marginalia-mode)) (use-package crux :bind ("C-c M-e" . crux-find-user-init-file) ("C-c C-w" . crux-transpose-windows) ("C-c M-d" . crux-find-current-directory-dir-locals-file) ("C-a" . crux-move-beginning-of-line)) (use-package magit :bind (("C-M-g" . magit-status))) (use-package nerd-icons-corfu :commands nerd-icons-corfu-formatter :defines corfu-margin-formatters) (use-package corfu :commands global-corfu-mode :custom (corfu-cycle t) (corfu-auto t) (corfu-auto-delay 1) (corfu-auto-prefix 3) (corfu-separator ?_) :hook (after-init . global-corfu-mode) :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) (use-package cape) (use-package orderless :custom (completion-styles '(orderless partial-completion basic)) (completion-category-defaults nil) (completion-category-overrides nil)) (use-package yasnippet :commands yas-global-mode :diminish yas-minor-mode :hook (after-init . yas-global-mode)) (use-package yasnippet-snippets :after yasnippet) (use-package exec-path-from-shell :commands exec-path-from-shell-initialize :custom (exec-path-from-shell-arguments nil) :hook (after-init . exec-path-from-shell-initialize)) (use-package nixpkgs-fmt :custom (nixpkgs-fmt-command "nixfmt")) (use-package eat :bind (("C-c e p" . eat-project) ("C-c e t" . eat))) (use-package f :demand t) (use-package envrc :commands envrc-global-mode :hook (after-init . envrc-global-mode)) (use-package gptel :commands gptel-make-anthropic f-read-text :config (gptel-make-anthropic "Claude" :stream t :key (f-read-text "/run/secrets/claude_key"))) (use-package sideline-flymake) (use-package sideline-eglot) (use-package sideline :custom (sideline-backends-right '(sideline-flymake sideline-eglot)) :hook (eglot-managed-mode . sideline-mode) (flymake-mode . sideline-mode)) (use-package eglot :custom (eglot-extend-to-xref t) (eglot-ignored-server-capabilities '(:inlayHintProvider)) (jsonrpc-event-hook nil) :hook (eglot-managed-mode . eldoc-box-hover-mode) (before-save . eldoc-format-buffer) :bind (:map eglot-mode-map ("C-c l a" . eglot-code-actions) ("C-c l r" . eglot-rename) ("C-c l h" . eldoc) ("C-c l g" . xref-find-references) ("C-c l w" . eglot-reconnect))) (use-package proced :custom (proced-auto-update-flag t) (proced-auto-update-interval 3) (proced-enable-color-flag t) (proced-show-remote-processes t)) (use-package org :ensure t :defer t :commands (org-mode org-capture org-agenda) :init (defvar org-journal-file "~/nextcloud/org/journal.org") (defvar org-archive-file "~/nextcloud/org/archive.org") (defvar org-notes-file "~/nextcloud/org/notes.org") (defvar org-inbox-file "~/nextcloud/org/inbox.org") (defvar org-work-file "~/nextcloud/org/work.org") (defun my/org-capture-project-target-heading () "Determine Org target headings from the current file's project path. This function assumes a directory structure like '~/projects/COMPANY/PROJECT/'. It extracts 'COMPANY' and 'PROJECT' to use as nested headlines for an Org capture template. If the current buffer is not visi ting a file within such a project structure, it returns nil, causing capture to default to the top of the file." (when-let* ((path (buffer-file-name))) ; Ensure we are in a file-visiting buffer (let ((path-parts (split-string path "/" t " "))) (when-let* ((projects-pos (cl-position "projects" path-parts :test #'string=)) (company (nth (+ 1 projects-pos) path-parts)) (project (nth (+ 2 projects-pos) path-parts))) ;; Return a list of headlines for Org to find or create. (list company project))))) :bind (("C-c c" . org-capture) ("C-c i" . org-store-link) ("C-c a" . org-agenda) :map org-mode-map ("C-c t" . org-toggle-inline-images) ("C-c l" . org-toggle-link-display)) :custom (org-agenda-files (list org-inbox-file org-journal-file)) (org-directory "~/nextcloud/org") (org-default-notes-file org-inbox-file) (org-archive-location (concat org-archive-file "::* From %s")) (org-log-done 'time) (org-log-into-drawer t) (org-hide-emphasis-markers t) (org-src-fontify-natively t) (org-src-tab-acts-natively t) (org-capture-templates '(("t" "Todo" entry (file org-inbox-file) "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n)") ("j" "Journal" entry (file+olp+datetree org-journal-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n") ("n" "Note" entry (file org-notes-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n") ("p" "Project Task" item (file+function org-work-file my/org-capture-project-target-heading) "* TODO %? \n CLOCK: %U" )) ) :config ;; Enable syntax highlighting in code blocks (add-hook 'org-mode-hook 'turn-on-font-lock) (add-hook 'org-mode-hook 'org-indent-mode)) ;; extras (use-package comp-run :ensure nil :config (push "tramp-loaddefs.el.gz" native-comp-jit-compilation-deny-list) (push "cl-loaddefs.el.gz" native-comp-jit-compilation-deny-list)) (use-package rustic :custom (rustic-lsp-client 'eglot)) (provide 'init) ;;; init.el ends here #+END_SRC ** =generated/modules/apps/wofi.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/modules/apps/wofi.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, ... }: let # Path to your configuration assets wofiAssets = ../../../assets/system/conf/wofi; # Read the files in that directory wofiFiles = builtins.readDir wofiAssets; # Build an attribute set mapping filenames to their full paths wofiConfs = lib.genAttrs (builtins.attrNames wofiFiles) (name: { src = "${wofiAssets}/${name}"; }); # Toggle for enabling Wofi enableWofi = true; in { # Module option to enable/disable Wofi options.enableWofi = lib.mkEnableOption "Enable Wofi terminal launcher"; # Everything in config is wrapped safely with mkIf config = lib.mkIf enableWofi { # Use myApps as a container for all your programs myApps = { wofi = { enable = true; assetsDir = wofiAssets; files = wofiConfs; # Example: you could reference a top-level user option user = config.defaultUser or "henrov"; }; }; }; } #+END_SRC