#+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 en configs]] --- * 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/assets/= - =generated//modules/= - =generated/hosts/= * 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 =.generated/.config/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 yes :mkdirp yes :eval never { 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"; }; import-tree.url = "github:vic/import-tree"; stylix = { url = "github:nix-community/stylix"; inputs.nixpkgs.follows = "nixpkgs"; }; flatpak = { url = "github:gmodena/nix-flatpak"; 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"; }; hyprland.url = "github:hyprwm/Hyprland"; }; outputs = { self, nixpkgs, home-manager, import-tree, stylix, hyprland, emacs-overlay, zen-browser, flatpak ... }: let system = "x86_64-linux"; flakeRoot = self; in { nixosConfigurations = { traveldroid = nixpkgs.lib.nixosSystem { inherit system; modules = [ ({ ... }: { nixpkgs.overlays = [ emacs-overlay.overlays.default ]; }) flatpak.nixosModules.default ./generated/hosts/traveldroid/host.nix ]; specialArgs = { inherit flakeRoot; inherit home-manager import-tree stylix hyprland zen-browser; }; }; }; }; } #+END_SRC ** =generated/hosts/traveldroid/host.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/host.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, import-tree, home-manager, ... }: let hostname = "traveldroid"; modulesPath = "${flakeRoot}/generated/modules/${hostname}"; usersPath = "${flakeRoot}/generated/users"; hostModules = import-tree modulesPath; globalUsers = import-tree usersPath; allModules = hostModules.imports ++ globalUsers.imports; in { ################################# # Core system config ################################# networking.hostName = hostname; system.stateVersion = "26.05"; ################################# # Imports ################################# imports = [ ../../../generated/users/henrov.nix ./boot.nix ./hardware-configuration.nix ] ++ allModules ++ [ home-manager.nixosModules.home-manager ]; # import HM last ################################# # Home Manager integration ################################# home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; # Install dconf for the system/user environment.systemPackages = [ pkgs.dconf ]; # Ensure Home Manager writes dconf safely programs.dconf.enable = true; } #+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 yes :mkdirp yes :eval never { 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/boot.nix= #+BEGIN_SRC nix :tangle generated/hosts/traveldroid/boot.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, flakeRoot, ... }: { boot.loader = { systemd-boot.enable = true; efi.canTouchEfiVariables = true; efi.efiSysMountPoint = "/boot"; timeout = 5; }; boot.kernelPackages = pkgs.linuxPackages_latest; boot.kernelParams = [ "quiet" "splash" "udev.log_level=3" "rd.systemd.show_status=false" ]; boot.consoleLogLevel = 0; #boot.initrd.systemd.enable = true; boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ]; boot.kernelModules = [ "kvm-intel" ]; boot.plymouth = { enable = true; /* theme = "rings"; themePackages = [ (pkgs.adi1090x-plymouth-themes.override { selected_themes = [ "rings" ]; }) ];*/ }; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; } #+END_SRC * Following are the imported modules * generated/traveldroid/modules/apps ** =generated/modules/traveldroid/apps/2_b_installed.nix= This installs a list of apps #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/2_b_installed.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, ... }: let ################################# # FILE ################################# confPath = "${flakeRoot}/generated/assets/2_b_installed.conf"; raw = builtins.readFile confPath; lines = lib.splitString "\n" raw; ################################# # CLEAN LINE ################################# cleanLine = line: let noCR = lib.replaceStrings [ "\r" ] [ "" ] line; noInlineComment = lib.head (lib.splitString "#" noCR); in lib.strings.trim noInlineComment; ################################# # PARSE SECTION ################################# parseSection = section: let result = builtins.foldl' (acc: line: let l = lib.strings.trim line; in if l == section then acc // { active = true; } else if lib.hasPrefix "#" l then acc // { active = false; } else if acc.active then acc // { entries = acc.entries ++ [ l ]; } else acc ) { active = false; entries = []; } lines; in builtins.filter (l: l != "") (map cleanLine result.entries); ################################# # NIX PACKAGES ################################# packageEntries = parseSection "#packages"; resolvePkg = name: let parts = lib.splitString "." name; found = lib.attrByPath parts null pkgs; in if found == null then throw '' packages.nix: package not found Token: ${name} File : ${confPath} '' else found; packages = map resolvePkg packageEntries; ################################# # FLATPAKS ################################# flatpakEntries = parseSection "#flatpaks"; in { ################################# # Allow unfree ################################# nixpkgs.config.allowUnfree = true; ################################# # System packages (Nix) ################################# environment.systemPackages = packages; ################################# # Flatpak setup ################################# services.flatpak.enable = true; services.flatpak.remotes = [ { name = "flathub"; location = "https://flathub.org/repo/flathub.flatpakrepo"; } ]; ################################# # Flatpak apps ################################# services.flatpak.packages = flatpakEntries; } #+END_SRC ** =generated/assets/2_b_installed.conf= This is a list of additional apps to install #+BEGIN_SRC conf :tangle generated/assets/2_b_installed.conf :noweb yes :mkdirp yes :eval never #packages todoist brave chromium git direnv ripgrep wget kdePackages.kdeconnect-kde _1password-gui tree gparted file htop btop bat wev solaar baobab duf zed-editor eza z-lua qdirstat obsidian onlyoffice-desktopeditors postman tea python3 nextcloud-client nextcloud-talk-desktop signal-desktop openssl audacity handbrake spotify vlc #flatpaks eu.betterbird.Betterbird com.todoist.Todoist #+END_SRC ** =generated/modules/traveldroid/apps/kitty.nix= This file sets up Kitty terminal #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/kitty.nix :noweb yes :mkdirp yes :eval never { lib, pkgs, config, flakeRoot,... }: let ################################# # Determine default username ################################# username = config.defaultUser or "henrov"; moduleName = "kitty"; ################################# # Paths to assets ################################# assetPath = "${flakeRoot}/generated/.config/kitty"; programFiles = builtins.readDir assetPath; # Convert asset files into a nix attribute set files = lib.genAttrs (builtins.attrNames programFiles) (name: { source = "${assetPath}/${name}"; }); in { ################################# # System-wide packages ################################# environment.systemPackages = [ pkgs.kitty ]; ################################# # Home Manager user configuration ################################# _module.args.hmUsers = { ${username} = { # Enable Kitty through Home Manager programs.kitty.enable = true; # Extra user-specific config snippet programs.kitty.extraConfig = '' # Include the Catppuccin-Mocha theme include themes/Catppuccin-Mocha.conf ''; # Map all asset files into ~/.config/kitty/ home.file = lib.mkMerge ( map (name: { ".config/${moduleName}/${name}" = { source = files.${name}.source; }; }) (builtins.attrNames files) ); }; }; } #+END_SRC ** =.config/kitty/Catppuccin-Mocha.conf= These are config files for .config/kitty #+BEGIN_SRC conf :tangle generated/.config/kitty/Catppuccin-Mocha.conf :noweb yes :mkdirp yes :eval never # vim:ft=kitty ## name: Catppuccin Kitty Mocha ## author: Catppuccin Org ## license: MIT ## upstream: https://github.com/catppuccin/kitty/blob/main/themes/mocha.conf ## blurb: Soothing pastel theme for the high-spirited! # The basic colors foreground #cdd6f4 background #1e1e2e selection_foreground #1e1e2e selection_background #f5e0dc # Cursor colors cursor #f5e0dc cursor_text_color #1e1e2e # Scrollbar colors scrollbar_handle_color #9399b2 scrollbar_track_color #45475a # URL color when hovering with mouse url_color #f5e0dc # Kitty window border colors active_border_color #b4befe inactive_border_color #6c7086 bell_border_color #f9e2af # OS Window titlebar colors wayland_titlebar_color system macos_titlebar_color system # Tab bar colors active_tab_foreground #11111b active_tab_background #cba6f7 inactive_tab_foreground #cdd6f4 inactive_tab_background #181825 tab_bar_background #11111b # Colors for marks (marked text in the terminal) mark1_foreground #1e1e2e mark1_background #b4befe mark2_foreground #1e1e2e mark2_background #cba6f7 mark3_foreground #1e1e2e mark3_background #74c7ec # The 16 terminal colors # black color0 #45475a color8 #585b70 # red color1 #f38ba8 color9 #f38ba8 # green color2 #a6e3a1 color10 #a6e3a1 # yellow color3 #f9e2af color11 #f9e2af # blue color4 #89b4fa color12 #89b4fa # magenta color5 #f5c2e7 color13 #f5c2e7 # cyan color6 #94e2d5 color14 #94e2d5 # white color7 #bac2de color15 #a6adc8 #+END_SRC ** =.config/kitty/kitty.conf= These are config files for .config/kitty #+BEGIN_SRC conf :tangle generated/.config/kitty/kitty.conf :noweb yes :mkdirp yes :eval never shell_integration no-rc include Catppuccin-Mocha.conf map ctrl+shift+v paste_from_clipboard map ctrl+shift+c copy_to_clipboard background_opacity 0.2 background_blur 1 dynamic_background_opacity yes font_family FiraCode Nerd Font font_size 10.0 #+END_SRC ** =generated/modules/traveldroid/apps/starship.nix= This file sets up starship prompt #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/starship.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, ... }: let # Default username fallback username = config.defaultUser or "henrov"; # Path to the starship config in assets starshipConfSrc = "${flakeRoot}/generated/.config/starship.toml"; in { ################################# # Enable Starship system-wide ################################# environment.systemPackages = [ pkgs.starship ]; ################################# # Home Manager user configuration ################################# _module.args.hmUsers = { ${username} = { programs.starship = { enable = true; }; # Copy the starship.toml from assets to ~/.config/starship.toml home.file = { ".config/starship.toml" = { source = starshipConfSrc; }; }; }; }; } #+END_SRC ** =.config/starship.toml= These are config files for .config #+BEGIN_SRC toml :tangle generated/.config/starship.toml :noweb yes :mkdirp yes :eval never "$schema" = 'https://starship.rs/config-schema.json' format = """ [](red)\ $os\ $username\ [](bg:peach fg:red)\ $directory\ [](bg:yellow fg:peach)\ $git_branch\ $git_status\ [](fg:yellow bg:green)\ $c\ $rust\ $golang\ $nodejs\ $php\ $java\ $kotlin\ $haskell\ $python\ [](fg:green bg:sapphire)\ $conda\ [](fg:sapphire bg:lavender)\ $time\ [ ](fg:lavender)\ $cmd_duration\ $line_break\ $character""" palette = 'catppuccin_mocha' [os] disabled = false style = "bg:red fg:crust" [os.symbols] Windows = "" Ubuntu = "󰕈" SUSE = "" Raspbian = "󰐿" Mint = "󰣭" Macos = "󰀵" Manjaro = "" Linux = "󰌽" Gentoo = "󰣨" Fedora = "󰣛" Alpine = "" Amazon = "" Android = "" AOSC = "" Arch = "󰣇" Artix = "󰣇" CentOS = "" Debian = "󰣚" Redhat = "󱄛" RedHatEnterprise = "󱄛" [username] show_always = true style_user = "bg:red fg:crust" style_root = "bg:red fg:crust" format = '[ $user]($style)' [directory] style = "bg:peach fg:crust" format = "[ $path ]($style)" truncation_length = 3 truncation_symbol = "…/" [directory.substitutions] "Documents" = "󰈙 " "Downloads" = " " "Music" = "󰝚 " "Pictures" = " " "Developer" = "󰲋 " [git_branch] symbol = "" style = "bg:yellow" format = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)' [git_status] style = "bg:yellow" format = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)' [nodejs] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [c] symbol = " " style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [rust] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [golang] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [php] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [java] symbol = " " style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [kotlin] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [haskell] symbol = "" style = "bg:green" format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)' [python] symbol = "" style = "bg:green" format = '[[ $symbol( $version)(\(#$virtualenv\)) ](fg:crust bg:green)]($style)' [docker_context] symbol = "" style = "bg:sapphire" format = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)' [conda] symbol = "  " style = "fg:crust bg:sapphire" format = '[$symbol$environment ]($style)' ignore_base = false [time] disabled = false time_format = "%R" style = "bg:lavender" format = '[[  $time ](fg:crust bg:lavender)]($style)' [line_break] disabled = false [character] disabled = false success_symbol = '[❯](bold fg:green)' error_symbol = '[❯](bold fg:red)' vimcmd_symbol = '[❮](bold fg:green)' vimcmd_replace_one_symbol = '[❮](bold fg:lavender)' vimcmd_replace_symbol = '[❮](bold fg:lavender)' vimcmd_visual_symbol = '[❮](bold fg:yellow)' [cmd_duration] show_milliseconds = true format = " in $duration " style = "bg:lavender" disabled = false show_notifications = true min_time_to_notify = 45000 [palettes.catppuccin_mocha] rosewater = "#f5e0dc" flamingo = "#f2cdcd" pink = "#f5c2e7" mauve = "#cba6f7" red = "#f38ba8" maroon = "#eba0ac" peach = "#fab387" yellow = "#f9e2af" green = "#a6e3a1" teal = "#94e2d5" sky = "#89dceb" sapphire = "#74c7ec" blue = "#89b4fa" lavender = "#b4befe" text = "#cdd6f4" subtext1 = "#bac2de" subtext0 = "#a6adc8" overlay2 = "#9399b2" overlay1 = "#7f849c" overlay0 = "#6c7086" surface2 = "#585b70" surface1 = "#45475a" surface0 = "#313244" base = "#1e1e2e" mantle = "#181825" crust = "#11111b" [palettes.catppuccin_frappe] rosewater = "#f2d5cf" flamingo = "#eebebe" pink = "#f4b8e4" mauve = "#ca9ee6" red = "#e78284" maroon = "#ea999c" peach = "#ef9f76" yellow = "#e5c890" green = "#a6d189" teal = "#81c8be" sky = "#99d1db" sapphire = "#85c1dc" blue = "#8caaee" lavender = "#babbf1" text = "#c6d0f5" subtext1 = "#b5bfe2" subtext0 = "#a5adce" overlay2 = "#949cbb" overlay1 = "#838ba7" overlay0 = "#737994" surface2 = "#626880" surface1 = "#51576d" surface0 = "#414559" base = "#303446" mantle = "#292c3c" crust = "#232634" [palettes.catppuccin_latte] rosewater = "#dc8a78" flamingo = "#dd7878" pink = "#ea76cb" mauve = "#8839ef" red = "#d20f39" maroon = "#e64553" peach = "#fe640b" yellow = "#df8e1d" green = "#40a02b" teal = "#179299" sky = "#04a5e5" sapphire = "#209fb5" blue = "#1e66f5" lavender = "#7287fd" text = "#4c4f69" subtext1 = "#5c5f77" subtext0 = "#6c6f85" overlay2 = "#7c7f93" overlay1 = "#8c8fa1" overlay0 = "#9ca0b0" surface2 = "#acb0be" surface1 = "#bcc0cc" surface0 = "#ccd0da" base = "#eff1f5" mantle = "#e6e9ef" crust = "#dce0e8" [palettes.catppuccin_macchiato] rosewater = "#f4dbd6" flamingo = "#f0c6c6" pink = "#f5bde6" mauve = "#c6a0f6" red = "#ed8796" maroon = "#ee99a0" peach = "#f5a97f" yellow = "#eed49f" green = "#a6da95" teal = "#8bd5ca" sky = "#91d7e3" sapphire = "#7dc4e4" blue = "#8aadf4" lavender = "#b7bdf8" text = "#cad3f5" subtext1 = "#b8c0e0" subtext0 = "#a5adcb" overlay2 = "#939ab7" overlay1 = "#8087a2" overlay0 = "#6e738d" surface2 = "#5b6078" surface1 = "#494d64" surface0 = "#363a4f" base = "#24273a" mantle = "#1e2030" crust = "#181926" #+END_SRC ** =generated/modules/traveldroid/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/traveldroid/apps/thunar.nix :noweb yes :mkdirp yes :eval never { pkgs, config, lib, ... }: let # Resolve the default username from host config username = config.defaultUser or "henrov"; in { ############################ # System-level packages ############################ environment.systemPackages = with pkgs; [ thunar # main file manager thunar-archive-plugin # zip, tar, rar, 7z support thunar-volman # auto-mount removable drives gvfs # support for external drives and network shares xarchiver # optional GUI archive manager ]; ############################ # Home Manager user-level configuration ############################ # Direct assignment to the user avoids recursiveUpdate issues home-manager.users."${username}" = { home.stateVersion = "26.05"; # required home.sessionVariables = { FILE_MANAGER = "thunar"; USERNAME = username; }; }; } #+END_SRC ** =generated/modules/traveldroid/apps/wofi.nix= This is the install for Wofi, the launcher #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/wofi.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, ... }: let username = config.defaultUser or "henrov"; assetPath = "${flakeRoot}/generated/.config/wofi"; in { environment.systemPackages = [ pkgs.wofi ]; home-manager.users = { ${username} = { home.file = { ".config/wofi/config" = { text = builtins.readFile "${assetPath}/config"; force = true; }; ".config/wofi/style.css" = { text = builtins.readFile "${assetPath}/style.css"; force = true; }; }; }; }; } #+END_SRC ** =.config/wofi/config= These are config files for .config/wofi #+BEGIN_SRC ini :tangle generated/.config/wofi/config :noweb yes :mkdirp yes :eval never [global] allow_images = true allow_markup = true show_drun = true:apps,false:others show_run = true show_files = false show_windowed = false show_dmenu = false show_ssh = false show_power = false width = 800 height = 600 # Center on the active monitor location=center anchor=center lines = 10 columns = 1 sort_order = last-used sort_method = fuzzy allow_scrolling = true scroll_wrap = true scroll_step = 10 cycle = true hide_scroll = false hide_search = false show_labels = true label_search = true label_run = Run label_files = Files label_windowed = Windows label_drun = Applications label_dmenu = Commands label_ssh = SSH label_power = Power prompt = > #+END_SRC ** =.config/wofi/style.css= These are config files for .config/wofi #+BEGIN_SRC css :tangle generated/.config/wofi/style.css :noweb yes :mkdirp yes :eval never /* Catppuccin Mocha theme for Wofi with transparency and rounded corners */ @define-color base rgba(30, 30, 46, 0.9); /* Added transparency */ @define-color surface0 rgba(49, 50, 68, 0.95); /* Added transparency */ @define-color surface1 #45475A; @define-color surface2 #585B70; @define-color text #CDD6F4; @define-color lavender #B4BEFE; @define-color blue #89B4FA; @define-color sapphire #74C7EC; @define-color teal #94E2D5; @define-color green #A6E3A1; @define-color yellow #F9E2AF; @define-color peach #FAB387; @define-color maroon #EBA0AC; @define-color red #F38BA8; @define-color mauve #CBA6F7; @define-color pink #F5C2E7; @define-color flamingo #F2CDCD; @define-color rosewater #F5E0DC; * { background-color: transparent; color: @text; font-family: "JetBrainsMono Nerd Font", monospace; font-size: 12pt; } #main { background-color: @base; border: 1px solid @surface0; border-radius: 10px; /* Rounded corners */ padding: 20px; box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); } #input { background-color: @surface0; color: @text; border: 1px solid @surface1; border-radius: 10px; /* Rounded corners */ padding: 5px 10px; margin-bottom: 10px; } #entry { background-color: rgba( 200, 200, 200, 0.2 ); /* very light grey, very transparent */ color: @text; border-radius: 10px; padding: 5px 10px; margin: 2px 0; } #entry:focus { background-color: @surface1; color: @lavender; border-radius: 10px; /* Rounded corners */ } #entry:selected { background-color: @surface2; color: @text; border-radius: 10px; /* Rounded corners */ } #scrollbar { background-color: @surface0; border-radius: 10px; /* Rounded corners */ width: 8px; } #scrollbar.handle { background-color: @blue; border-radius: 10px; /* Rounded corners */ } #+END_SRC ** =generated/modules/traveldroid/apps/zenbrowser.nix= This installs zen browser #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/zenbrowser.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, zen-browser, ... }: let # Grab the Zen Browser package for this host system zenBrowser = zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default; in { environment.systemPackages = [ zenBrowser ]; } #+END_SRC ** =generated/modules/traveldroid/apps/zsh.nix= This sets up the zsh in the terminal #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/zsh.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, flakeRoot, ... }: let username = config.users.users.defaultUser or "henrov"; generatedZsh = "${flakeRoot}/generated/.config/zsh/.zshrc"; in { ################################# # Home Manager Zsh configuration ################################# _module.args.hmUsers = { ${username} = { programs.zsh = { enable = true; enableCompletion = true; # autocd = true; ohMyZsh = { enable = true; theme = ""; plugins = [ "git" "sudo" "extract" "colored-man-pages" "command-not-found" "history" "docker" "kubectl" ]; }; autosuggestions.enable = true; syntaxHighlighting.enable = true; }; # Use ~/.config/zsh as ZDOTDIR home.sessionVariables = { ZDOTDIR = "${config.home.homeDirectory}/.config/zsh"; }; # Deploy the generated .zshrc home.file.".config/zsh/.zshrc".source = generatedZsh; }; }; } #+END_SRC ** =generated/.config/zsh/.zshrc This sets up the zsh in the terminal #+BEGIN_SRC bash :tangle generated/.config/zsh/.zshrc :noweb yes :mkdirp yes :eval never # 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/traveldroid/apps/emacs/emacs.nix= This installs emacs #+BEGIN_SRC nix :tangle generated/modules/traveldroid/apps/emacs/emacs.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, flakeRoot, ... }: let username = config.defaultUser or "henrov"; assetPath = "${flakeRoot}/generated/.config/emacs"; # Emacs package with Tree-sitter support emacsPkg = pkgs.emacs-pgtk.override { withTreeSitter = true; }; # Extra packages for Emacs via Home Manager emacsExtraPackages = epkgs: [ epkgs.manualPackages.treesit-grammars.with-all-grammars epkgs.nerd-icons epkgs.doom-modeline epkgs.diminish epkgs.eldoc epkgs.pulsar epkgs.which-key epkgs.expreg epkgs.vundo epkgs.puni epkgs.avy epkgs.consult epkgs.vertico epkgs.marginalia epkgs.crux epkgs.magit epkgs.nerd-icons-corfu epkgs.corfu epkgs.cape epkgs.orderless epkgs.yasnippet epkgs.yasnippet-snippets epkgs.rg epkgs.exec-path-from-shell epkgs.eat epkgs.rust-mode epkgs.rustic epkgs.nix-mode epkgs.hcl-mode epkgs.shell-pop epkgs.envrc epkgs.nixpkgs-fmt epkgs.f epkgs.gptel epkgs.catppuccin-theme epkgs.eldoc-box epkgs.sideline epkgs.sideline-flymake epkgs.sideline-eglot ]; in { # System-wide installation environment.systemPackages = [ emacsPkg ]; # Home Manager user-specific configuration for your default user _module.args.hmUsers = { ${username} = { home.sessionVariables = { EDITOR = "emacs"; XDG_SCREENSHOTS_DIR = "~/screenshots"; }; programs.emacs = { enable = true; package = emacsPkg; extraPackages = emacsExtraPackages; }; home.file = { ".emacs.d/early-init.el" = { source = "${assetPath}/early-init.el"; force = true; # <-- allow overwrite }; ".emacs.d/init.el" = { source = "${assetPath}/init.el"; force = true; # <-- allow overwrite }; }; }; }; } #+END_SRC ** =generated/.config/emacs/early-init.el= This contaions emacs #+BEGIN_SRC el :tangle generated/.config/emacs/early-init.el :noweb yes :mkdirp yes :eval never ;;; 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/.config/emacs/init.el= This contaions emacs #+BEGIN_SRC el :tangle generated/.config/emacs/init.el :noweb yes :mkdirp yes :eval never ;;; 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/traveldroid/desktop ** =generated/modules/traveldroid/desktop/fonts.nix= This file installs and configures fonts #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/fonts.nix :noweb yes :mkdirp yes :eval never { lib, pkgs, config, ... }: { fonts.packages = with pkgs; [ nerd-fonts.iosevka nerd-fonts.fira-code nerd-fonts.jetbrains-mono ]; } #+END_SRC ** =generated/modules/traveldroid/desktop/gtk.nix= Setting up GTK #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/gtk.nix :noweb yes :mkdirp yes :eval never { pkgs, config, lib, ... }: let username = config.defaultUser or "henrov"; in { environment.systemPackages = with pkgs; [ gtk3 gtk4 ]; home-manager.users."${username}" = { gtk = { enable = true; }; }; } #+END_SRC ** =generated/modules/traveldroid/desktop/hyprland.nix= Setting up Hyprland #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/hyprland.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, home-manager, inputs, ... }: let username = config.defaultUser or "henrov"; assetPath = "${flakeRoot}/generated/.config/hypr"; hyprlandPkg = pkgs.hyprland or pkgs.hyprland-git or inputs.hyprland.packages.${pkgs.system}.default; in { # Install Hyprland systemwide environment.systemPackages = [ hyprlandPkg ]; # Home Manager user configuration home-manager.users = { ${username} = { home.file = { ".config/hypr/animations.conf" = { source = "${assetPath}/animations.conf"; force = true; }; ".config/hypr/behaviour.conf" = { source = "${assetPath}/behaviour.conf"; force = true; }; ".config/hypr/bindings.conf" = { source = "${assetPath}/bindings.conf"; force = true; }; ".config/hypr/exec-once.conf" = { source = "${assetPath}/exec-once.conf"; force = true; }; ".config/hypr/hypridle.conf" = { source = "${assetPath}/hypridle.conf"; force = true; }; ".config/hypr/hyprland.conf" = { source = "${assetPath}/hyprland.conf"; force = true; }; ".config/hypr/hyprlock.conf" = { source = "${assetPath}/hyprlock.conf"; force = true; }; ".config/hypr/layer-rules.conf" = { source = "${assetPath}/layer-rules.conf"; force = true; }; ".config/hypr/layout.conf" = { source = "${assetPath}/layout.conf"; force = true; }; ".config/hypr/monitor-rules.conf" = { source = "${assetPath}/monitor-rules.conf"; force = true; }; ".config/hypr/scripts/layout-selector.sh" = { source = "${assetPath}/scripts/layout-selector.sh"; executable = true; force = true; }; ".config/hypr/theming.css" = { source = "${assetPath}/theming.css"; force = true; }; ".config/hypr/window-rules.conf" = { source = "${assetPath}/window-rules.conf"; force = true; }; ".config/hypr/# exec-once" = { source = "${assetPath}/# exec-once"; force = true; }; }; }; }; } #+END_SRC ** =.config/hypr/animations.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/animations.conf :noweb yes :mkdirp yes :eval never # ./assets/conf/desktop/hypr/animations.conf animations { enabled = yes bezier = myBezier, 0.05, 0.9, 0.1, 1.05 animation = windows, 1, 7, myBezier animation = windowsOut, 1, 7, default, popin 80% animation = border, 1, 10, default animation = borderangle, 1, 8, default animation = fade, 1, 7, default animation = workspaces, 1, 6, default } #+END_SRC ** =.config/hypr/behaviour.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/behaviour.conf :noweb yes :exports code :wrap nil :mkdirp yes :eval never # Keyboard and mouse settings input { kb_layout = us kb_options = ctrl:nocaps sensitivity = -0.5 accel_profile = adaptive scroll_factor = 0.5 } # Scrolling modifier settings input { scroll_main_mod = alt scroll_main_mod_invert = no scroll_per_border = yes } # Touchpad settings (applies to all touchpads) input:touchpad: * { natural_scroll = yes scroll_factor = 0.5 } # Focus settings focus { follow_mouse = yes new_windows = smart } # Miscellaneous settings misc { resize_step = 10 10 anim_resize_friction = 0.1 } #+END_SRC ** =.config/hypr/bindings.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/bindings.conf :noweb yes :mkdirp yes :eval never $mainMod = SUPER # use walker to show exec menu # bind = $mainMod, Space , exec, walker # bind = $mainMod, P, pseudo # bind = $mainMod, T, togglesplit # grimblast # bind = $mainMod SHIFT, P, exec, grimblast -n -f copysave active # bind = $mainMod SHIFT, A, exec, grimblast -n -f copysave area # bind = $mainMod ALT, P, exec, grimblast -n -f copysave output # bind = $mainMod CTRL, P, exec, grimblast -n -f copysave screen # Terminal / launcher / kill / reload bind = $mainMod, E, exec, thunar bind = $mainMod, RETURN, exec, kitty bind = $mainMod, Space, exec, wofi --show drun bind = ALT, Space, exec, wofi --show drun bind = $mainMod, Q, killactive, bind = $mainMod SHIFT, Q, exit, bind = $mainMod SHIFT, R, exec, hyprctl reload # Switch windows bind = ALT, TAB, cyclenext, # bind = ALT SHIFT, TAB, cyclenext prev # switch layouts # Hyprscrolling bind = $mainMod, period, layoutmsg, move +col bind = $mainMod, comma, layoutmsg, swapcol l # Make / break a tab-group (stack) bind = $mainMod, S, togglegroup # Cycle tabs in the group bind = $mainMod, L, changegroupactive, f bind = $mainMod, H, changegroupactive, b bind = $mainMod, T, exec, ~/.config/hypr/scripts/layout-selector.sh # Focus movement bind = $mainMod, H, movefocus, l bind = $mainMod, L, movefocus, r bind = $mainMod, K, movefocus, u bind = $mainMod, J, movefocus, d bind = $mainMod, left, movefocus, l bind = $mainMod, right, movefocus, r bind = $mainMod, up, movefocus, u bind = $mainMod, down, movefocus, d # Move windows bind = $mainMod SHIFT, H, movewindow, l bind = $mainMod SHIFT, L, movewindow, r bind = $mainMod SHIFT, K, movewindow, u bind = $mainMod SHIFT, J, movewindow, d bind = $mainMod SHIFT, left, movewindow, l bind = $mainMod SHIFT, right, movewindow, r bind = $mainMod SHIFT, up, movewindow, u bind = $mainMod SHIFT, down, movewindow, d # Resize windows bind = $mainMod CTRL, H, resizeactive, -30 0 bind = $mainMod CTRL, L, resizeactive, 30 0 bind = $mainMod CTRL, K, resizeactive, 0 -30 bind = $mainMod CTRL, J, resizeactive, 0 30 # Floating / fullscreen bind = $mainMod, V, togglefloating, bind = $mainMod, F, fullscreen, 0 bind = $mainMod SHIFT, F, fullscreen, 1 # Workspaces bind = $mainMod, 1, workspace, 1 bind = $mainMod, 2, workspace, 2 bind = $mainMod, 3, workspace, 3 bind = $mainMod, 4, workspace, 4 bind = $mainMod, 5, workspace, 5 bind = $mainMod, 6, workspace, 6 bind = $mainMod, 7, workspace, 7 bind = $mainMod, 8, workspace, 8 bind = $mainMod, 9, workspace, 9 bind = $mainMod, 0, workspace, 10 bind = $mainMod SHIFT, 1, movetoworkspace, 1 bind = $mainMod SHIFT, 2, movetoworkspace, 2 bind = $mainMod SHIFT, 3, movetoworkspace, 3 bind = $mainMod SHIFT, 4, movetoworkspace, 4 bind = $mainMod SHIFT, 5, movetoworkspace, 5 bind = $mainMod SHIFT, 6, movetoworkspace, 6 bind = $mainMod SHIFT, 7, movetoworkspace, 7 bind = $mainMod SHIFT, 8, movetoworkspace, 8 bind = $mainMod SHIFT, 9, movetoworkspace, 9 bind = $mainMod SHIFT, 0, movetoworkspace, 10 # Cycle workspaces bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_up, workspace, e-1 # Mouse drag bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:273, resizewindow ######################### # Screenshots ######################### bind = $mainMod SHIFT, s, exec, grim -g "$(slurp)" - | wl-copy bind = , XF86Screenshot, exec, grim - | wl-copy ######################### # Audio (pamixer) ######################### bind = , XF86AudioRaiseVolume, exec, pamixer -i 5 bind = , XF86AudioLowerVolume, exec, pamixer -d 5 bind = , XF86AudioMute, exec, pamixer -t bind = , XF86AudioMicMute, exec, pamixer --default-source -t ######################### # Media (playerctl) ######################### bind = , XF86AudioPlay, exec, playerctl play-pause bind = , XF86AudioPause, exec, playerctl pause bind = , XF86AudioNext, exec, playerctl next bind = , XF86AudioPrev, exec, playerctl previous bind = , XF86AudioStop, exec, playerctl stop ######################### # Brightness (brightnessctl) ######################### bind = , XF86MonBrightnessUp, exec, brightnessctl set +10% bind = , XF86MonBrightnessDown, exec, brightnessctl set 10%- bind = , XF86KbdBrightnessUp, exec, brightnessctl -d '*kbd_backlight*' set +10% bind = , XF86KbdBrightnessDown, exec, brightnessctl -d '*kbd_backlight*' set 10%- ######################### # Power / session ######################### bind = , XF86Sleep, exec, systemctl suspend bind = , XF86PowerOff, exec, systemctl poweroff bind = , XF86WakeUp, exec, systemctl suspend bind = $mainMod, L, exec, loginctl lock-session # bind = $mainMod, X, exec, ~/.config/hypr/scripts/powermenu.sh ######################### # Laptop lid settings ######################### bindl = , switch:on:Lid Switch, exec, ~/.config/hypr/scripts/lid-action.sh bindl = , switch:off:Lid Switch, exec, ~/.config/hypr/scripts/lid-restore.sh ######################### # Start apps ######################### bind = CTRL ALT, B, exec, flatpak run eu.betterbird.Betterbird bind = CTRL ALT, S, exec, spotify bind = $mainMod, Z, exec, zeditor bind = $mainMod, W, exec, zen #+END_SRC ** =.config/hypr/exec-once.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/exec-once.conf :noweb yes :mkdirp yes :eval never exec-once = dbus-update-activation-environment --systemd --all exec-once = hypridleconfig/hypr/exec-once exec-once = hyprpolkitagent exec-once = systemd-run --user --scope --unit=elephant elephant exec-once = bash -c "sleep 5 && waybar" exec-once = swww-daemon & swww img -o eDP-1 ~/Wallpapers/pictures/1.jpg exec-once = sh ~/Wallpapers/scripts/wallpaper.sh & #+END_SRC ** =.config/hypr/hypridle.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/hypridle.conf :noweb yes :mkdirp yes :eval never general { lock_cmd = hyprlock after_sleep_cmd = hyprctl dispatch dpms on ignore_dbus_inhibit = false } listener { timeout = 600 on-timeout = hyprlock } listener { timeout = 900 on-timeout = hyprctl dispatch dpms off on-resume = hyprctl dispatch dpms on } #+END_SRC ** =.config/hypr/hyprland.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/hyprland.conf :noweb yes :mkdirp yes :eval never source = ./theming.css source = ./animations.conf source = ./bindings.conf # source = ./behaviour.conf source = ./exec-once.conf source = ./layer-rules.conf source = ./layout.conf source = ./monitor-rules.conf # source = ./window-rules.conf source = ./# exec-once exec-once = /nix/store/c9cnbxhxbagj7gfpc1g5hl4x4f8dzayv-dbus-1.16.2/bin/dbus-update-activation-environment --systemd DISPLAY HYPRLAND_INSTANCE_SIGNATURE WAYLAND_DISPLAY XDG_CURRENT_DESKTOP XDG_SESSION_TYPE && systemctl --user stop hyprland-session.target && systemctl --user start hyprland-session.target decoration { shadow { color=rgba(1e1e2e99) } } general { col.active_border=0xff97cbcd 0xff89b4fa col.inactive_border=rgb(45475a) } group { groupbar { col.active=rgb(89b4fa) col.inactive=rgb(45475a) text_color=rgb(cdd6f4) } col.border_active=rgb(89b4fa) col.border_inactive=rgb(45475a) col.border_locked_active=rgb(94e2d5) } misc { background_color=rgb(1e1e2e) } #+END_SRC ** =.config/hypr/hyprlock.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/hyprlock.conf :noweb yes :mkdirp yes :eval never # ~/.config/hypr/hyprlock.conf general { grace = 2 ignore_empty_input = true } background { path = ~/.config/hypr/lock.png blur_passes = 2 blur_size = 6 } input-field { size = 320, 60 outline_thickness = 2 dots_size = 0.25 dots_spacing = 0.20 fade_on_empty = true placeholder_text = "Password" position = 0, -120 halign = center valign = center } label { text = $TIME font_size = 72 position = 0, 120 halign = center valign = center } #+END_SRC ** =.config/hypr/layer-rules.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/layer-rules.conf :noweb yes :mkdirp yes :eval never layerrule = blur on, ignore_alpha 1, match:namespace waybar layerrule = xray 1, match:namespace waybar layerrule = blur on, ignore_alpha 1, match:namespace walker layerrule = xray 1, match:namespace walker layerrule = blur on, ignore_alpha 1, match:namespace swaync-control-center layerrule = blur on, ignore_alpha 1, match:namespace swaync-notification-window #+END_SRC ** =.config/hypr/layout.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/layout.conf :noweb yes :mkdirp yes :eval never workspace_layouts = dwindle, master, scrolling, monocle #+END_SRC ** =.config/hypr/monitor-rules.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/monitor-rules.conf :noweb yes :mkdirp yes :eval never # Default portable monitor rule monitor=DP-1,3840x1080@144,1920x0,1 #+END_SRC ** =.config/hypr/scripts/layout-selector.sh= These are config files for .config/hypr/scripts #+BEGIN_SRC bash :tangle generated/.config/hypr/scripts/layout-selector.sh :noweb yes :mkdirp yes :eval never #!/usr/bin/env bash # layout-selector.sh # Select a workspace layout using Wofi, shows description, applies with layoutmsg # Define layouts and descriptions declare -A LAYOUTS=( [dwindle]="舘 Dwindle: Auto-tiling, windows shrink progressively" [master]=" Master: One main window, others stacked" [scrolling]=" Scrolling: Vertical list, scroll through windows" [monocle]=" Monocle: One window fills the screen" [floating]=" Floating: Free move & resize" ) ORDER=(dwindle master scrolling monocle floating) # Prepare Wofi menu: show "layoutname: description" MENU_ITEMS=() for key in "${ORDER[@]}"; do MENU_ITEMS+=("$key: ${LAYOUTS[$key]}") done # Show selection menu via Wofi CHOICE=$(printf '%s\n' "${MENU_ITEMS[@]}" | wofi --dmenu --prompt "Select Layout") # Exit if cancelled [ -z "$CHOICE" ] && exit 0 # Extract layout name from selection (before colon) LAYOUT_NAME="${CHOICE%%:*}" # Apply layout via layoutmsg hyprctl dispatch layoutmsg setlayout "$LAYOUT_NAME" # Show OSD feedback hyprctl dispatch oSD "Layout: $LAYOUT_NAME" 2000 #+END_SRC ** =.config/hypr/theming.css= These are config files for .config/hypr #+BEGIN_SRC css :tangle generated/.config/hypr/theming.css :noweb yes :mkdirp yes :eval never # Hyprland Catppuccin Mocha Theme (solid colors) # Colors $base = #1e1e2e $mantle = #181825 $surface0 = #313244 $surface1 = #45475a $surface2 = #585b70 $text = #cdd6f4 $rosewater = #f5e0dc $lavender = #b4befe $red = #f38ba8 $peach = #fab387 $yellow = #f9e2af $green = #a6e3a1 $teal = #94e2d5 $blue = #89b4fa $mauve = #cba6f7 $flamingo = #f2cdcd $inactive = #595959aa # General theming general { gaps_in = 2 gaps_out = 4 border_size = 4 layout = scrolling resize_on_border = true extend_border_grab_area = 20 # Solid-color borders #col.active_border = "0xff97cbcd 0xff89b4fa" #col.active_border = #a6e3a1 #col.inactive_border = #595959aa } # Window decorations decoration { rounding = 8 } #+END_SRC ** =.config/hypr/window-rules.conf= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/window-rules.conf :noweb yes :mkdirp yes :eval never # Floating and centering nm-connection-editor windowrule = float, nm-connection-editor windowrule = move center, nm-connection-editor windowrule = size 900 700, nm-connection-editor # Center all new windows by default windowrule = center, ^(.*) # Example: Float specific apps (uncomment to use) windowrule = float, ^(pavucontrol)$ # Make Wofi windows blurred windowrulev2 = floatclass:Wofi,blur:15 windowrulev2 = floatclass:Wofi,floating:true windowrulev2 = floatclass:Wofi,opacity:0.9,blur:15 # Move specific apps to workspaces automatically #windowrule = move workspace 1, ^(kitty)$ #windowrule = move workspace 2, ^(zen)$ #windowrule = move workspace 3, ^(libreoffice)$ #+END_SRC ** =.config/hypr/# exec-once= These are config files for .config/hypr #+BEGIN_SRC conf :tangle generated/.config/hypr/# exec-once :noweb yes :mkdirp yes :eval never #Load random wallpaper workspacecreated = exec $HOME/.local/bin/wallpaper-sync-and-set.sh $workspace # Workspace definitions (modern syntax) # workspace = 1 # workspace = 2 # workspace = 3 # workspace = 4 # workspace = 5 # Auto-launch apps on specific workspaces (use `exec` with `workspace` rule) # exec-once = kitty, workspace 1 # exec-once = flatpak run app.betterbird.zen, workspace 2 # exec-once = zen, workspace 3 # Force a specific layout for a workspace # workspace 1, layout:dwindle # workspace 2, layout:master # workspace 3, layout:msg # Set workspace persistence # workspace 1, persistent:true # workspace 2, persistent:true # Workspace behavior # workspace { # cycle_move_empty = no #} #+END_SRC ** =generated/modules/traveldroid/desktop/wallpaper.nix= Setting up wallpaper engine + wallpaper gui #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/wallpaper.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, ... }: let username = config.defaultUser or "henrov"; homeDir = "/home/${username}"; wallpaperSrc = "${flakeRoot}/assets/traveldroid/Wallpapers"; wallpaperDst = "${homeDir}/Wallpapers"; randoScript = "${homeDir}/Wallpapers/scripts/randomizeWallpapers.sh"; in { # Make bash available environment.systemPackages = [ pkgs.bash pkgs.rsync pkgs.jq pkgs.swww pkgs.waypaper pkgs.socat ]; # Create the copy script using Home Manager, following Waybar style home-manager.users = { ${username} = { home.file = { "copy-wallpapers.sh" = { text = '' #!/run/current-system/sw/bin/bash set -euo pipefail echo "Running as $(whoami)" echo "Copying wallpapers from ${wallpaperSrc} to ${wallpaperDst} ..." if [ ! -d "${wallpaperSrc}" ]; then echo "ERROR: ${wallpaperSrc} does not exist" exit 1 fi mkdir -p "${wallpaperDst}" # Simple copy, overwrite everything cp -r "${wallpaperSrc}/." "${wallpaperDst}/" # Fix permissions chmod -R u+rwx "${wallpaperDst}" echo "Done copying wallpapers." ''; executable = true; force = true; }; }; }; }; # User service to run the script that copies the Wallpaperstuff systemd.user.services.copyWallpapers = { description = "Copy wallpapers from repo to ~/Wallpapers"; serviceConfig = { Type = "oneshot"; ExecStart = "${homeDir}/copy-wallpapers.sh"; Restart = "no"; WorkingDirectory = homeDir; }; wantedBy = [ "default.target" ]; }; # User service to randomize wallpapers systemd.user.services.randomizeWallpapers = { description = "Randomize wallpapers in ~/Wallpapers/pictures"; serviceConfig = { Type = "oneshot"; ExecStart = "${randoScript}"; Restart = "no"; WorkingDirectory = homeDir; }; wantedBy = [ "default.target" ]; }; ############################ # Random background per workspace at logon ############################ systemd.user.services.workspaceWallpapers = { description = "Dynamic wallpapers per workspace for Hyprland"; after = [ "graphical-session.target" ]; wants = [ "graphical-session.target" ]; serviceConfig = { ExecStart = "${homeDir}/Wallpapers/scripts/workspace-wallpapers.sh"; Restart = "always"; }; wantedBy = [ "default.target" ]; }; } #+END_SRC ** =generated/modules/traveldroid/desktop/stylix.nix= #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/stylix.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, stylix, ... }: let username = config.defaultUser or "henrov"; moduleName = "stylix"; assetPath = "${flakeRoot}/generated/.config/${moduleName}"; assetFiles = builtins.attrNames (builtins.readDir assetPath); stylixFiles = lib.genAttrs assetFiles (f: { name = ".config/${moduleName}/${f}"; value = { source = "${assetPath}/${f}"; }; }); stylixConfFile = "${assetPath}/stylix.conf"; stylixConf = if builtins.pathExists stylixConfFile then builtins.readFile stylixConfFile else ""; cursorName = "phinger-cursors-light"; cursorSize = 24; in { ################################# # Enable Stylix module ################################# imports = [ stylix.nixosModules.stylix ]; ################################# # System packages ################################# environment.systemPackages = [ pkgs.feh pkgs.st ]; ################################# # Stylix system config ################################# stylix = { enable = true; base16Scheme = "${flakeRoot}/assets/traveldroid/theming/stylix/catppuccin-mocha.yaml"; polarity = "dark"; targets = { gtk.enable = true; qt.enable = true; }; # Define FULL cursor set OR remove entirely cursor = { name = cursorName; package = pkgs.phinger-cursors; size = cursorSize; }; }; ################################# # Home Manager ################################# _module.args.hmUsers = { "${username}" = { home.file = lib.mkMerge [ stylixFiles { ".config/${moduleName}/stylix.conf".text = stylixConf; } ]; home.sessionVariables = { STYLIX_CONF = "$HOME/.config/stylix/stylix.conf"; XCURSOR_THEME = cursorName; XCURSOR_SIZE = toString cursorSize; HYPRCURSOR_THEME = cursorName; HYPRCURSOR_SIZE = toString cursorSize; }; gtk.theme.name = lib.mkForce "Catppuccin-Mocha-Standard-Blue-Dark"; }; }; } #+END_SRC ** =.config/stylix/stylix.conf= These are config files for .config/stylix #+BEGIN_SRC conf :tangle generated/.config/stylix/stylix.conf :noweb yes :mkdirp yes :eval never enable = true; base16Scheme = ../../../assets/system/theming/stylix/catppuccin-mocha.yaml; image = ../../../assets/hyprland/wallpaperstuff/pictures/wall1.jpg; polarity = "dark"; cursor = { package = "phinger-cursors"; # symbolic reference name = "phinger-cursors-light"; size = 24; }; fonts = { monospace = { package = "nerd-fonts-fira-code"; name = "Fira Code Nerd Font"; }; sansSerif = { package = "lato"; name = "Lato"; }; }; icons = { enable = true; package = "papirus-icon-theme"; dark = "Papirus-Dark"; light = "Papirus-Light"; }; #+END_SRC ** =.config/stylix/palette.json= These are config files for .config/stylix #+BEGIN_SRC json :tangle generated/.config/stylix/palette.json :noweb yes :mkdirp yes :eval never { "base00": "1e1e2e", "base01": "181825", "base02": "313244", "base03": "45475a", "base04": "585b70", "base05": "cdd6f4", "base06": "f5e0dc", "base07": "b4befe", "base08": "f38ba8", "base09": "fab387", "base0A": "f9e2af", "base0B": "a6e3a1", "base0C": "94e2d5", "base0D": "89b4fa", "base0E": "cba6f7", "base0F": "f2cdcd", "author": "https://github.com/catppuccin/catppuccin", "scheme": "Catppuccin Mocha", "slug": "catppuccin-mocha" } #+END_SRC ** =.config/stylix/palette.html= These are config files for .config/stylix #+BEGIN_SRC html :tangle generated/.config/stylix/palette.html :noweb yes :mkdirp yes :eval never

Primary colors

00
01
02
03
04
05
06
07

Accents

08
09
0A
0B
0C
0D
0E
0F

Documentation

Each color should be used as described in this table.

See the Stylix documentation for how to apply these colors on NixOS.

#+END_SRC ** =generated/modules/traveldroid/desktop/waybar.nix= This file installs and configures waybar #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/waybar.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, ... }: let # Use the config option defaultUser directly, fallback to "henrov" username = config.defaultUser or "henrov"; assetPath = "${flakeRoot}/generated/.config/waybar"; in { # Install Waybar system-wide environment.systemPackages = [ pkgs.waybar ]; home-manager.users = { ${username} = { home.file = { ".config/waybar/config" = { text = builtins.readFile "${assetPath}/config"; force = true; }; ".config/waybar/style.css" = { text = builtins.readFile "${assetPath}/style.css"; force = true; }; }; }; }; # Systemd user service for Waybar systemd.user.services.waybar = { description = "Waybar for Hyprland"; after = [ "graphical-session.target" ]; serviceConfig = { ExecStart = "${pkgs.waybar}/bin/waybar"; Restart = "always"; Environment = '' WAYLAND_DISPLAY=${config.environment.sessionVariables.WAYLAND_DISPLAY or "wayland-0"} XDG_CURRENT_DESKTOP=Hyprland ''; }; wantedBy = [ "default.target" ]; }; } #+END_SRC ** =.config/waybar/config= These are config files for waybar #+BEGIN_SRC conf :tangle generated/.config/waybar/config :noweb yes :mkdirp yes :eval never { "layer": "top", "height": 34, //"modules-left": ["hyprland/window"], "modules-center": ["hyprland/workspaces" ], "modules-right": [ "idle_inhibitor", "pulseaudio", "network", // "cpu", // "memory", // "temperature", "battery", "tray", "clock", "custom/notifications", ], /* "custom/notifications": { "tooltip": false, "return-type": "json", "exec-if": "which swaync-client", "exec": "swaync-client -swb", "format": "{icon}", "format-icons": { "notification": "", "none": "", "dnd-notification": "󰂠", "dnd-none": "󰪓", }, "on-click": "swaync-client -t", "on-click-right": "swaync-client -d", "on-click-middle": "swaync-client -dn", }, */ "idle_inhibitor": { "tooltip": true, "format": "{icon}", "format-icons": { "activated": "  ", "deactivated": " 󰒲 ", }, "tooltip-format-activated": "Staying awake", "tooltip-format-deactivated": "Might sleep....", }, "pulseaudio": { "format": "{volume}% {icon}", "format-bluetooth": "{volume}% {icon}", "format-muted": "", "format-icons": { "headphones": "", "headset": "", "phone": "", "portable": "", "default": ["", ""], }, "on-click": "pavucontrol", }, "network": { "format-wifi": " ({bandwidthDownBits})", "format-ethernet": " ({bandwidthDownBits})", "format-disconnected": "Disconnected ⚠", "tooltip-format-wifi": "{essid} ({signalStrength}%)", "tooltip-format-ethernet": "{ifname}: {ipaddr}/{cidr}", "on-click": "impala", "on-click-right": "nm-connection-editor", }, "cpu": { "format": "{usage}%  ", "tooltip": false, }, "memory": { "format": "{percentage}%  ", }, "temperature": { "format": "{temperatureC}°C ", "tooltip": false, }, "tray": { "spacing": 10, "icon-size": 14, }, "clock": { "format": "{:%a, %d %b %Y - %H:%M}", "tooltip": false, "on-click": "flatpak run eu.betterbird.Betterbird -calendar", }, "battery": { "bat": "BAT0", "states": { "good": 95, "warning": 30, "critical": 15, }, "format": "{capacity}% {icon}", "format-charging": "{capacity}% 󰂄", "format-plugged": "{capacity}%  ", "format-icons": ["󰁺", "󰁼", "󰁾", "󰂀", "󱈏 "], }, } #+END_SRC ** =.config/waybar/style.css= These are config files for waybar #+BEGIN_SRC css :tangle generated/.config/waybar/config :noweb yes :mkdirp yes :eval never /* --- Hyprland palette (ported) --- */ @define-color base rgba(30, 30, 46, 1.0); /* 1e1e2eff */ @define-color inactive rgba(89, 89, 89, 0.667); /* 595959aa */ @define-color blue rgba(51, 204, 255, 0.933); /* 33ccffee */ @define-color green rgba(0, 255, 153, 0.933); /* 00ff99ee */ /* extra colors you referenced but didn’t define */ @define-color text rgba(255, 255, 255, 1.0); @define-color surface1 rgba(255, 255, 255, 0.08); @define-color subtext1 rgba(255, 255, 255, 0.35); @define-color red rgba(255, 0, 0, 0.90); @define-color overlay1 rgba(255, 255, 255, 0.35); @define-color yellow rgba(255, 215, 0, 0.95); * { font-family: Aporetic Sans Mono, Iosevka Nerd Font, Roboto, Helvetica, Arial, sans-serif; font-size: 13px; } window#waybar { background-color: transparent; color: @text; transition-property: background-color; border-bottom: 0px solid rgba(0, 0, 0, 0); transition-duration: 0.5s; } #workspaces button { padding: 0px 1px; min-width: 80px; background-color: transparent; color: @text; border: 2px solid @inactive; border-radius: 10px; } #custom-notifications.empty { color: @overlay1; } #custom-notifications.unread { color: @yellow; } #workspaces button:hover { background-color: @surface1; color: @text; } #workspaces button.active { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; font-weight: bold; border: 1px solid transparent; background: linear-gradient(rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.15)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.overflow { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; font-weight: bold; border: 1px dashed transparent; background: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.overflow { background: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.hidden { padding: 0; margin: 0; min-width: 0; border: 0; background: transparent; opacity: 0; } #clock, #idle_inhibitor, #battery, #cpu, #memory, #temperature, #network, #pulseaudio, #tray { margin: 0 5px; padding: 0 2px; } #idle_inhibitor.activated { background-color: @green; } #battery.charging { color: @green; } @keyframes blink { to { background-color: #ffffff; color: black; } } #battery.warning:not(.charging) { color: white; animation-name: blink; animation-duration: 0.5s; animation-timing-function: linear; animation-iteration-count: infinite; animation-direction: alternate; } #window, #workspaces { margin: 0 4px; } .modules-left > widget:first-child > #workspaces { margin-left: 0; } .modules-right > widget:last-child > #workspaces { margin-right: 0; } #network.disconnected { background-color: @red; } #temperature.critical { background-color: @red; } /* ========================================================= * Notifications * ========================================================= */ #custom-notifications { margin: 0 4px; padding: 0 4px; min-width: 0; } #custom-notifications.empty { color: @overlay1; } #custom-notifications.unread { color: @yellow; } /* ========================================================= * Hyprscroll overflow indicator (custom/hyprscroll_overflow) * States: .ok, .overflow, .error * ========================================================= */ /* Default (no overflow): subtle pill, still hoverable for tooltip */ #custom-hyprscroll_overflow.ok { padding: 0px 1px; min-width: 80px; color: @subtext1; border-radius: 10px; /* subtle outline so you know it's there */ border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(255, 255, 255, 0.03); } /* Make it feel interactive (hover) */ #custom-hyprscroll_overflow.ok:hover { color: @text; background-color: @surface1; border: 1px solid rgba(255, 255, 255, 0.18); } /* Overflow state: you already have this; keep it. Optional: add hover tweak so it "pops" a bit. */ #custom-hyprscroll_overflow.overflow:hover { background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } /* Error state: clear but not screaming */ #custom-hyprscroll_overflow.error { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; border: 1px solid rgba(255, 0, 0, 0.55); background: rgba(255, 0, 0, 0.15); font-weight: bold; } /* Optional: if you keep .hidden in the script for any reason */ #custom-hyprscroll_overflow.hidden { padding: 0; margin: 0; min-width: 0; border: 0; background: transparent; opacity: 0; } #+END_SRC ** =.config/waypaper/config.ini= These are config files for waypaper #+BEGIN_SRC conf :tangle generated/.config/waypaper/config.ini :noweb yes :mkdirp yes :eval never [Settings] language = en backend = swww folder = ~/Wallpapers/pictures monitors = All wallpaper = ~/Wallpapers/pictures/13.jpg show_path_in_tooltip = True fill = fill sort = name color = #ffffff subfolders = False all_subfolders = False show_hidden = False show_gifs_only = False zen_mode = False post_command = number_of_columns = 3 swww_transition_type = any swww_transition_step = 63 swww_transition_angle = 0 swww_transition_duration = 2 swww_transition_fps = 60 mpvpaper_sound = False mpvpaper_options = use_xdg_state = False stylesheet = /home/henrov/.config/waypaper/style.css keybindings = ~/.config/waypaper/keybindings.ini #+END_SRC ** =generated/modules/traveldroid/desktop/wayland.nix= #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/wayland.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, ... }: { ################################# # Core Wayland packages ################################# environment.systemPackages = with pkgs; [ wayland wl-clipboard # optional but commonly used for copy/paste ]; ################################# # Optional: enable graphics stack ################################# hardware.graphics.enable = true; ################################# # Optional session variables for Wayland ################################# environment.sessionVariables = { # Forces some apps to use Wayland NIXOS_OZONE_WL = "1"; }; } #+END_SRC ** =generated/modules/traveldroid/desktop/xdg.nix= This sets the XDG implementation #+BEGIN_SRC nix :tangle generated/modules/traveldroid/desktop/xdg.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, inputs, ... }: let ################################# # Default username fallback ################################# username = config.defaultUser or "henrov"; ################################# # Determine XDG portal package ################################# xdgPortalHyprlandPkg = pkgs.xdg-desktop-portal-hyprland or inputs.xdgPortalHyprland.packages.${pkgs.system}.default; in { ################################# # System-wide packages ################################# environment.systemPackages = [ xdgPortalHyprlandPkg ]; ################################# # Home Manager user config ################################# _module.args.hmUsers = { ${username} = { home.packages = [ xdgPortalHyprlandPkg ]; # Enable XDG portal integration for Hyprland xdg.portal = { enable = true; extraPortals = [ xdgPortalHyprlandPkg ]; config.hyprland = { "org.freedesktop.impl.portal.Screencast" = [ "hyprland" ]; }; }; }; }; } #+END_SRC * generated/modules/traveldroid/system ** =generated/modules/traveldroid/system/bluetooth.nix= #+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/bluetooth.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, flakeRoot, home-manager, ... }: let username = config.defaultUser or "henrov"; in { ############################ # Bluetooth daemon ############################ hardware.bluetooth = { enable = true; powerOnBoot = true; package = pkgs.bluez; # singular, not a list }; ############################ # GUI Bluetooth manager ############################ environment.systemPackages = with pkgs; [ blueman ]; ############################ # Optional Home Manager integration ############################ _module.args.hmUsers = lib.mkIf (home-manager != null) { ${username} = { # If you want a graphical tray or manager accessible in user session home.packages = [ pkgs.blueman ]; # Example: could drop any config files for blueman here home.file = {}; }; }; } #+END_SRC ** =generated/modules/traveldroid/system/dbus.nix= This sets the dbus implementation #+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/dbus.nix :noweb yes :mkdirp yes :eval never { config, pkgs, ... }: { # Enable classic D-Bus service services.dbus.enable = true; # Use default dbus package (classic D-Bus) services.dbus.dbusPackage = pkgs.dbus; # Include some essential system packages so shell and tools exist environment.systemPackages = with pkgs; [ bashInteractive coreutils ]; # Do not attempt to wrap dbus-daemon-launch-helper manually # No extra security.wrappers needed } #+END_SRC ** =generated/modules/traveldroid/system/login-tuigreet.nix= This sets up tuigreeter which is not fancy but imo fits the aesthetic I am aiming for #+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/login-tuigreet.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, ... }: let tuigreetBin = "${pkgs.tuigreet}/bin/tuigreet"; sessionsDir = "${pkgs.hyprland}/share/wayland-sessions"; in { ################################# # Greetd (tuigreet) ################################# services.greetd = { enable = true; settings = { default_session = { command = '' ${tuigreetBin} \ --time \ --remember \ --remember-session \ --sessions ${sessionsDir} \ --cmd "start-hyprland" ''; user = "greeter"; }; }; }; ################################# # Fix TTY / boot noise issues ################################# systemd.services.greetd.serviceConfig = { Type = "idle"; StandardInput = "tty"; StandardOutput = "tty"; StandardError = "journal"; # Prevent boot log spam on tty TTYReset = true; TTYVHangup = true; TTYVTDisallocate = true; }; } #+END_SRC ** =generated/modules/traveldroid/system/networking.nix= This sets the networking. #+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/networking.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, ... }: { ################################# # Networking core ################################# networking = { # Let DHCP be default unless overridden elsewhere useDHCP = lib.mkDefault true; # Hostname comes from host.nix, do NOT redefine here ################################# # NetworkManager (primary stack) ################################# networkmanager = { enable = true; # Use iwd backend for WiFi wifi.backend = "iwd"; }; ################################# # iwd (WiFi daemon) ################################# wireless.iwd = { enable = true; # Allow user control via NM / CLI settings.General.EnableNetworkConfiguration = true; }; ################################# # Firewall ################################# firewall = { enable = true; # KDE Connect support allowedTCPPortRanges = [ { from = 1714; to = 1764; } ]; allowedUDPPortRanges = [ { from = 1714; to = 1764; } ]; }; }; ################################# # System packages ################################# environment.systemPackages = [ pkgs.networkmanager ]; } #+END_SRC ** =generated/modules/traveldroid/system/nix.nix= #+BEGIN_SRC nix :tangle generated/modules/traveldroid/system/nix.nix :noweb yes :mkdirp yes :eval never { lib, config, ... }: { nix.settings = { experimental-features = [ "nix-command" "flakes" ]; download-buffer-size = 536870912; # 512 MB cores = 2; max-jobs = 1; }; } #+END_SRC * generated/users ** =generated/parked/users/copy_config_2_config.nix= This copies stuff to the user home-folder #+BEGIN_SRC nix :tangle generated/parked/users/copy_config_2_config.nix :noweb yes :mkdirp yes :eval never { config, pkgs, lib, flakeRoot, ... }: let username = config.users.users.defaultUser or "henrov"; configDir = "/home/${username}/.config"; assetPath = "${flakeRoot}/.config"; in { environment.systemPackages = [ pkgs.rsync ]; systemd.services.copyAssets = { description = "Copy assets to ${username}'s .config directory"; wantedBy = [ "multi-user.target" ]; # oneshot service runs once at boot serviceConfig.Type = "oneshot"; # Always use /bin/sh -c for multi-line commands serviceConfig.ExecStart = '' /bin/sh -c ' echo "Copying assets from ${assetPath} to ${configDir} ..." if [ ! -d "${assetPath}" ]; then echo "ERROR: ${assetPath} does not exist" exit 1 fi mkdir -p "${configDir}" chown -R u+rwx ${username}:${username} "${configDir}" ${pkgs.rsync}/bin/rsync -a --no-owner --no-group "${assetPath}/" "${configDir}/" # Fix .config permissions mkdir -p "${configDir}" chown -R ${username}:${username} "${configDir}" chmod -R u+rwx "${configDir}" echo "Done copying config files." ' ''; }; } #+END_SRC ** =generated/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/users/henrov.nix :noweb yes :mkdirp yes :eval never { lib, config, pkgs, ... }: let username = "henrov"; in { ################################# # NixOS system user ################################# users.users.${username} = { isNormalUser = true; home = "/home/${username}"; hashedPassword = "$6$S7iShgBxB.77CwmP$i0njK.2r3OL5UEvgZbmwZ0rnpZ4QyJcv8p9uCmJ4AiVPSMXkQkIwMLzyAOnJ0q8.tPLIp/7EquEIZeK8qbmgw/"; extraGroups = [ "wheel" "networkmanager" ]; }; ################################# # Home Manager user definition ################################# _module.args.hmUsers = { ${username} = { home.username = username; home.homeDirectory = "/home/${username}"; home.stateVersion = "26.05"; home.packages = [ # add packages here ]; home.file = { # Activation to ensure the directory is writable before symlinks home.activation.fixStylixPermissions = lib.hm.dag.entryAfter ["writeBoundary"] '' mkdir -p $HOME/.config chmod -R u+rwx $HOME/.config ''; }; }; }; } #+END_SRC * These are all the prepared config files :PROPERTIES: :CUSTOM_ID: the-config-files :END: ** =.config/waybar/style.css= These are config files for .config/waybar #+BEGIN_SRC css :tangle generated/.config/waybar/style.css :noweb yes :mkdirp yes :eval never /* --- Hyprland palette (ported) --- */ @define-color base rgba(30, 30, 46, 1.0); /* 1e1e2eff */ @define-color inactive rgba(89, 89, 89, 0.667); /* 595959aa */ @define-color blue rgba(51, 204, 255, 0.933); /* 33ccffee */ @define-color green rgba(0, 255, 153, 0.933); /* 00ff99ee */ /* extra colors you referenced but didn’t define */ @define-color text rgba(255, 255, 255, 1.0); @define-color surface1 rgba(255, 255, 255, 0.08); @define-color subtext1 rgba(255, 255, 255, 0.35); @define-color red rgba(255, 0, 0, 0.90); @define-color overlay1 rgba(255, 255, 255, 0.35); @define-color yellow rgba(255, 215, 0, 0.95); * { font-family: Aporetic Sans Mono, Iosevka Nerd Font, Roboto, Helvetica, Arial, sans-serif; font-size: 13px; } window#waybar { background-color: transparent; color: @text; transition-property: background-color; border-bottom: 0px solid rgba(0, 0, 0, 0); transition-duration: 0.5s; } #workspaces button { padding: 0px 1px; min-width: 80px; background-color: transparent; color: @text; border: 2px solid @inactive; border-radius: 10px; } #custom-notifications.empty { color: @overlay1; } #custom-notifications.unread { color: @yellow; } #workspaces button:hover { background-color: @surface1; color: @text; } #workspaces button.active { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; font-weight: bold; border: 1px solid transparent; background: linear-gradient(rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0.15)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.overflow { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; font-weight: bold; border: 1px dashed transparent; background: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.overflow { background: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.05)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } #custom-hyprscroll_overflow.hidden { padding: 0; margin: 0; min-width: 0; border: 0; background: transparent; opacity: 0; } #clock, #idle_inhibitor, #battery, #cpu, #memory, #temperature, #network, #pulseaudio, #tray { margin: 0 5px; padding: 0 2px; } #idle_inhibitor.activated { background-color: @green; } #battery.charging { color: @green; } @keyframes blink { to { background-color: #ffffff; color: black; } } #battery.warning:not(.charging) { color: white; animation-name: blink; animation-duration: 0.5s; animation-timing-function: linear; animation-iteration-count: infinite; animation-direction: alternate; } #window, #workspaces { margin: 0 4px; } .modules-left > widget:first-child > #workspaces { margin-left: 0; } .modules-right > widget:last-child > #workspaces { margin-right: 0; } #network.disconnected { background-color: @red; } #temperature.critical { background-color: @red; } /* ========================================================= * Notifications * ========================================================= */ #custom-notifications { margin: 0 4px; padding: 0 4px; min-width: 0; } #custom-notifications.empty { color: @overlay1; } #custom-notifications.unread { color: @yellow; } /* ========================================================= * Hyprscroll overflow indicator (custom/hyprscroll_overflow) * States: .ok, .overflow, .error * ========================================================= */ /* Default (no overflow): subtle pill, still hoverable for tooltip */ #custom-hyprscroll_overflow.ok { padding: 0px 1px; min-width: 80px; color: @subtext1; border-radius: 10px; /* subtle outline so you know it's there */ border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(255, 255, 255, 0.03); } /* Make it feel interactive (hover) */ #custom-hyprscroll_overflow.ok:hover { color: @text; background-color: @surface1; border: 1px solid rgba(255, 255, 255, 0.18); } /* Overflow state: you already have this; keep it. Optional: add hover tweak so it "pops" a bit. */ #custom-hyprscroll_overflow.overflow:hover { background: linear-gradient(rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.1)) padding-box, linear-gradient(45deg, @blue, @green) border-box; } /* Error state: clear but not screaming */ #custom-hyprscroll_overflow.error { padding: 0px 1px; min-width: 80px; color: @text; border-radius: 10px; border: 1px solid rgba(255, 0, 0, 0.55); background: rgba(255, 0, 0, 0.15); font-weight: bold; } /* Optional: if you keep .hidden in the script for any reason */ #custom-hyprscroll_overflow.hidden { padding: 0; margin: 0; min-width: 0; border: 0; background: transparent; opacity: 0; } #+END_SRC ** =.config/waypaper/config.ini= These are config files for .config/waypaper #+BEGIN_SRC conf :tangle generated/.config/waypaper/config.ini :noweb yes :mkdirp yes :eval never [Settings] language = en backend = swww folder = ~/Wallpapers/pictures monitors = All wallpaper = ~/Wallpapers/pictures/13.jpg show_path_in_tooltip = True fill = fill sort = name color = #ffffff subfolders = False all_subfolders = False show_hidden = False show_gifs_only = False zen_mode = False post_command = number_of_columns = 3 swww_transition_type = any swww_transition_step = 63 swww_transition_angle = 0 swww_transition_duration = 2 swww_transition_fps = 60 mpvpaper_sound = False mpvpaper_options = use_xdg_state = False stylesheet = /home/henrov/.config/waypaper/style.css keybindings = ~/.config/waypaper/keybindings.ini #+END_SRC ** =.config/zed/settings.json= These are config files for .config/zed #+BEGIN_SRC json :tangle generated/.config/zed/settings.json :noweb yes :mkdirp yes :eval never // Zed settings // // For information on how to configure Zed, see the Zed // documentation: https://zed.dev/docs/configuring-zed // // To see all of Zed's default settings without changing your // custom settings, run `zed: open default settings` from the // command palette (cmd-shift-p / ctrl-shift-p) { "icon_theme": "Catppuccin Mocha", "agent": { "default_model": { "provider": "ollama", "model": "codellama:34b", "enable_thinking": false }, "favorite_models": [], "model_parameters": [] }, "ui_font_size": 16, "buffer_font_size": 15, "theme": { "mode": "dark", "light": "One Light", "dark": "Catppuccin Mocha", }, } #+END_SRC