Files
nixos/Droidnix/README.org
T
2026-04-01 21:28:10 +02:00

99 KiB
Raw Blame History

Droidnix: A Dendritic NixOS + Home Manager Configuration NixOS Configuration Structure

Introduction   intro

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.

Root Level

  • flake.nix is the entry point and imports:

    • generated/assets/
    • generated/<host>/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 .#<hostname>.

The Assets Folder   assets

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

This section contains the Org blocks for tangling Nix code into the generated folders.

flake.nix

The Nix flake definition for Droidnix.

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

    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."nix-flatpak"
            ./generated/hosts/traveldroid/host.nix
            ./generated/users/henrov.nix
          ];
          specialArgs = {
            inherit flakeRoot;
            inherit home-manager import-tree stylix hyprland zen-browser;
          };
        };
      };
    };
}

generated/hosts/traveldroid/host.nix

{ lib, config, pkgs, flakeRoot, import-tree, home-manager, ... }:

let
  hostname = "traveldroid";
  modulesPath = "${flakeRoot}/generated/modules/${hostname}";
  hostModules = import-tree modulesPath;
  allModules = hostModules.imports;
in
{
  networking.hostName = hostname;
  system.stateVersion = "26.05";

  #################################
  # Locale
  #################################

  i18n = {
    defaultLocale = "nl_NL.UTF-8";
    extraLocales = [
      "nl_NL.UTF-8/UTF-8"
      "en_US.UTF-8/UTF-8"
    ];
    consoleKeyMap = "us";
  };

  time.timeZone = "Europe/Amsterdam";

  #################################
  # Imports
  #################################

  imports =
    [ ../../../generated/users/henrov.nix
      ./boot.nix
      ./hardware-configuration.nix
    ]
    ++ allModules
    ++ [ home-manager.nixosModules.home-manager ];

  #################################
  # Home Manager integration
  #################################

  home-manager.useGlobalPkgs = true;
  home-manager.useUserPackages = true;

  environment.systemPackages = [
    pkgs.dconf
  ];

  programs.dconf.enable = true;
}

generated/hosts/traveldroid/hardware-configuration.nix

  1. Boot into NixOS Live ISO or your installed system.
  2. Open a terminal.
  3. Run: <code>sudo nixos-generate-config root /mnt</code> (Omit root /mnt if already running NixOS.)
{
  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;
}

generated/hosts/traveldroid/boot.nix

{ 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"
  ];

  hardware.enableAllFirmware = true;

  boot.kernelModules = [ "kvm-intel" ];

  boot.plymouth = {
	    enable = true;
	  };



  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

Following are the imported modules

generated/traveldroid/modules/apps

generated/modules/traveldroid/apps/2_b_installed.nix

This installs a list of apps

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

generated/assets/2_b_installed.conf

This is a list of additional apps to install

#packages
bluez
blueman
usbutils
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

generated/modules/traveldroid/apps/kitty.nix

This file sets up Kitty terminal

{ lib, pkgs, config, flakeRoot, ... }:

let
  username = config.defaultUser or "henrov";

  extraConfigFile = "${flakeRoot}/generated/.config/kitty/extra.conf";

  extraConfig =
    if builtins.pathExists extraConfigFile
    then builtins.readFile extraConfigFile
    else "";
in
{
  #################################
  # System-wide install
  #################################
  environment.systemPackages = [
    pkgs.kitty
  ];

  #################################
  # Home Manager
  #################################
  home-manager.users = {
    "${username}" = {

      programs.kitty = {
        enable = true;

        settings = {
          confirm_os_window_close    = lib.mkForce 0;
          dynamic_background_opacity = lib.mkForce true;
          enable_audio_bell          = lib.mkForce false;
          mouse_hide_wait            = lib.mkForce "-1.0";
          window_padding_width       = lib.mkForce 10;
          background_opacity         = lib.mkForce "0.5";
          background_blur            = lib.mkForce 5;
        };

        extraConfig = ''
          ${extraConfig}

          # Theme
          include themes/Catppuccin-Mocha.conf
        '';
      };
    };
  };
}

generated/modules/traveldroid/apps/starship.nix

This file sets up starship prompt

{ 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
{
  #################################
  # Install Starship system-wide
  #################################
  environment.systemPackages = [ pkgs.starship ];

  #################################
  # Home Manager user configuration
  #################################
  home-manager.users = {
    ${username} = {

      home.file = {
        ".config/starship.toml" = {
          text = builtins.readFile "${starshipConfSrc}";
          force = true;
        };
      };
    };
  };
}

.config/starship.toml

These are config files for .config

"$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"

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

{ 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
    tumbler                  # Showing thumbnails
  ];

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

generated/modules/traveldroid/apps/wofi.nix

This is the install for Wofi, the launcher

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

.config/wofi/config

These are config files for .config/wofi

[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 = >

.config/wofi/style.css

These are config files for .config/wofi

/* 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 */
}

generated/modules/traveldroid/apps/zenbrowser.nix

This installs zen browser

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

generated/modules/traveldroid/apps/zsh.nix

This sets up the zsh in the terminal

{ lib, config, pkgs, flakeRoot, ... }:

let
  # Default username fallback
  username = config.defaultUser or "henrov";

  # Path to optional per-user generated zshrc
  generatedZsh = "${flakeRoot}/generated/.config/zsh/.zshrc";
in
{
  #################################
  # Install Zsh, Oh My Zsh, and Starship system-wide
  #################################
  environment.systemPackages = with pkgs; [
    zsh
    oh-my-zsh
    starship
  ];

  #################################
  # Set Zsh to use ~/.config/zsh as its config directory
  #################################
  environment.etc."zshenv".text = ''
    export ZDOTDIR=$HOME/.config/zsh
  '';

  #################################
  # Deploy global zshrc for all users
  #################################
  environment.etc."zshrc".text = ''
    export ZSH=${pkgs.oh-my-zsh}/share/oh-my-zsh
    ZSH_THEME=""
    plugins=(git sudo extract colored-man-pages command-not-found history docker kubectl)
    source $ZSH/oh-my-zsh.sh

    # Load optional per-user generated zshrc if it exists
    [ -f "${generatedZsh}" ] && source "${generatedZsh}"

    # Initialize Starship prompt
    eval "$(starship init zsh)"
  '';

  #################################
  # Set Zsh as default login shell for the user via Home Manager
  #################################
  home-manager.users = {
    ${username} = {
      programs.zsh.enable = true;

      # Include the generated zshrc if you want
      home.file.".config/zsh/.zshrc".source = generatedZsh;
      };
  };
}

=generated/.config/zsh/.zshrc

This sets up the zsh in the terminal

# Path to syntax highlighting installed by Nix
ZSH_SYNTAX_HIGHLIGHTING="${HOME}/.nix-pwofile/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"

# Load syntax highlighting if available
if [ -f "$ZSH_SYNTAX_HIGHLIGHTING" ]; then
    source "$ZSH_SYNTAX_HIGHLIGHTING"
fi

# Initialize Starship prompt
if command -v starship >/dev/null 2>&1; then
    eval "$(starship init zsh)"
fi

generated/modules/traveldroid/apps/emacs/emacs.nix

This installs emacs

{ 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
  home-manager.users = {
    ${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
        };
      };
    };
  };
}

generated/.config/emacs/early-init.el

This contaions emacs

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

generated/.config/emacs/init.el

This contaions emacs

;;; 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-<wheel-up>" . pixel-scroll-precision) ; dont zoom in please, just scroll
 ("C-<wheel-down>" . 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

generated/modules/traveldroid/desktop

generated/modules/traveldroid/desktop/fonts.nix

This file installs and configures fonts

{ lib, pkgs, config, ... }:

{
    fonts.packages = with pkgs; [
      nerd-fonts.iosevka
      nerd-fonts.fira-code
      nerd-fonts.jetbrains-mono
    ];
}

generated/modules/traveldroid/desktop/gtk.nix

Setting up GTK

{ pkgs, config, lib, ... }:

let
  username = config.defaultUser or "henrov";
in
{
  environment.systemPackages = with pkgs; [
    gtk3
    gtk4
  ];

  home-manager.users."${username}" = {
    gtk = {
      enable = true;
    };
  };
}

generated/modules/traveldroid/desktop/hyprland.nix

Setting up Hyprland

{ 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/workspace-rules.conf" = { source = "${assetPath}/workspace-rules.conf"; force = true; };
      };
    };
  };
}

.config/hypr/animations.conf

These are config files for .config/hypr

# ./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
}

.config/hypr/behaviour.conf

These are config files for .config/hypr

# Keyboard and mouse settings
input {
    kb_layout = us
    kb_options = ctrl:nocaps
    sensitivity = -0.5
    accel_pwofile = 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
}

.config/hypr/bindings.conf

These are config files for .config/hypr

$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

.config/hypr/exec-once.conf

These are config files for .config/hypr

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 = waybar
exec-once = swww-daemon & swww img -o eDP-1 ~/Wallpapers/pictures/1.jpg
exec-once = sh ~/Wallpapers/scripts/wallpaper.sh &

.config/hypr/hypridle.conf

These are config files for .config/hypr

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
}

.config/hypr/hyprland.conf

These are config files for .config/hypr

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 = ./workspace-rules.conf


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= 0xff89b4fa 0xff97cbcd
  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)
}

.config/hypr/hyprlock.conf

These are config files for .config/hypr

# ~/.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
}

.config/hypr/layer-rules.conf

These are config files for .config/hypr

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

.config/hypr/layout.conf

These are config files for .config/hypr

workspace_layouts = dwindle, master, scrolling, monocle

.config/hypr/monitor-rules.conf

These are config files for .config/hypr

# Default portable monitor rule
monitor=DP-1,3840x1080@144,1920x0,1

.config/hypr/scripts/layout-selector.sh

These are config files for .config/hypr/scripts

#!/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

.config/hypr/theming.css

These are config files for .config/hypr

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

.config/hypr/window-rules.conf

These are config files for .config/hypr

# 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)$

.config/hypr/workspace-rules.conf

These are config files for .config/hypr

#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
workspace = 6
workspace = 7
workspace = 8
workspace = 9
workspace = 10

generated/modules/traveldroid/desktop/wallpaper.nix

Setting up wallpaper engine + wallpaper gui

{ 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 = {
      Type = "simple";
      ExecStart = "${homeDir}/Wallpapers/scripts/workspace-wallpapers.sh";
      Restart = "on-failure";
      RestartSec = 5;
      WorkingDirectory = homeDir;
      Environment = [
        "HYPRLAND_INSTANCE_SIGNATURE=${builtins.getEnv "HYPRLAND_INSTANCE_SIGNATURE"}"
        "WAYLAND_DISPLAY=wayland-1"
        "PATH=/run/current-system/sw/bin:/usr/bin:/bin"
      ];
    };

    wantedBy = [ "default.target" ];
  };
}

generated/modules/traveldroid/desktop/stylix.nix

{ lib, config, pkgs, flakeRoot, stylix, ... }:

let
  username   = config.defaultUser or "henrov";
  moduleName = "stylix";

  assetPath  = "${flakeRoot}/generated/.config/${moduleName}";

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

    cursor = {
      name    = cursorName;
      package = pkgs.phinger-cursors;
      size    = cursorSize;
    };
  };

  #################################
  # Home Manager
  #################################
  home-manager.users = {
    "${username}" = {

      #################################
      # ONLY custom file (safe)
      #################################
      home.file.".config/stylix/stylix.conf" = {
        text  = stylixConf;
        force = true;
      };

      #################################
      # Environment variables
      #################################
      home.sessionVariables = {
        STYLIX_CONF      = "$HOME/.config/stylix/stylix.conf";
        XCURSOR_THEME    = cursorName;
        XCURSOR_SIZE     = toString cursorSize;
        HYPRCURSOR_THEME = cursorName;
        HYPRCURSOR_SIZE  = toString cursorSize;
      };
    };
  };
}

.config/stylix/stylix.conf

These are config files for .config/stylix

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

.config/stylix/palette.json

These are config files for .config/stylix

{
  "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"
}

.config/stylix/palette.html

These are config files for .config/stylix

<html>
    <head>
        <style>
            body {
                margin: 2rem;
                font-family: sans-serif;
            }
            body > div {
                display: flex;
                flex-direction: row;
                flex-wrap: wrap;
                gap: 1em;
            }
            body > div > div {
                width: 5rem;
                height: 5rem;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            #base00 { background-color: #1e1e2e; color: #cdd6f4; }
            #base01 { background-color: #181825; color: #cdd6f4; }
            #base02 { background-color: #313244; color: #cdd6f4; }
            #base03 { background-color: #45475a; color: #1e1e2e; }
            #base04 { background-color: #585b70; color: #1e1e2e; }
            #base05 { background-color: #cdd6f4; color: #1e1e2e; }
            #base06 { background-color: #f5e0dc; color: #1e1e2e; }
            #base07 { background-color: #b4befe; color: #1e1e2e; }
            #base08 { background-color: #f38ba8; color: #1e1e2e; }
            #base09 { background-color: #fab387; color: #1e1e2e; }
            #base0A { background-color: #f9e2af; color: #1e1e2e; }
            #base0B { background-color: #a6e3a1; color: #1e1e2e; }
            #base0C { background-color: #94e2d5; color: #1e1e2e; }
            #base0D { background-color: #89b4fa; color: #1e1e2e; }
            #base0E { background-color: #cba6f7; color: #1e1e2e; }
            #base0F { background-color: #f2cdcd; color: #1e1e2e; }
        </style>
    </head>
    <body>
        <h2>Primary colors</h2>
        <div>
            <div id="base00">00</div>
            <div id="base01">01</div>
            <div id="base02">02</div>
            <div id="base03">03</div>
            <div id="base04">04</div>
            <div id="base05">05</div>
            <div id="base06">06</div>
            <div id="base07">07</div>
        </div>

        <h2>Accents</h2>
        <div>
            <div id="base08">08</div>
            <div id="base09">09</div>
            <div id="base0A">0A</div>
            <div id="base0B">0B</div>
            <div id="base0C">0C</div>
            <div id="base0D">0D</div>
            <div id="base0E">0E</div>
            <div id="base0F">0F</div>
        </div>

        <h2>Documentation</h2>
        <p>Each color should be used as described in <a href="https://github.com/chriskempson/base16/blob/main/styling.md#styling-guidelines"> this table</a>.</p>
        <p>See the <a href="https://nix-community.github.io/stylix">Stylix documentation</a> for how to apply these colors on NixOS.</p>
    </body>
</html>

generated/modules/traveldroid/desktop/waybar.nix

This file installs and configures waybar

{ 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;
          };
          ".config/waybar/scripts/bluetooth-status.sh" = {
            text = builtins.readFile "${assetPath}/scripts/bluetooth-status.sh";
            force = true;
            executable = true;
          };
          ".config/waybar/scripts/hyprscroll-overflow.sh" = {
            text = builtins.readFile "${assetPath}/scripts/hyprscroll-overflow.sh";
            force = true;
            executable = true;
          };
          ".config/waybar/scripts/hyprscroll-menu.sh" = {
            text = builtins.readFile "${assetPath}/scripts/hyprscroll-menu.sh";
            force = true;
            executable = 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" ];
  };
}

.config/waybar/config

These are config files for waybar

{
  "layer": "top",
  "height": 34,

  //"modules-left":  ["hyprland/window"],

  "modules-center": [
    "hyprland/workspaces",
    "custom/hyprscroll_overflow"
  ],

  "modules-right": [
    "idle_inhibitor",
    "pulseaudio",
    "network",
    "custom/bluetooth",
    /*
    "cpu",
    "memory",
    "temperature",
    */
    "battery",
    "tray",
    "clock",
    ],

  "custom/hyprscroll_overflow": {
    "exec": "~/.config/waybar/scripts/hyprscroll-overflow.sh",
    "interval": 2,
    "return-type": "json",
    "format": "{}",
    "on-click": "~/.config/waybar/scripts/hyprscroll-menu.sh",
    "tooltip": true
  },

 /*
 "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",
  },

  "custom/bluetooth": {
    "exec": "~/.config/waybar/scripts/bluetooth-status.sh",
    "interval": 5,
    "return-type": "json",
    "on-click": "blueman-manager"
  },

  "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": ["󰁺", "󰁼", "󰁾", "󰂀", "󱈏 "],
  },
}

.config/waybar/style.css

These are config files for waybar

/* --- 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 didnt 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;
}

.config/waybar/scripts/bluetooth-status.sh

These are config files for waybar

#!/usr/bin/env bash
bt_connected=""
while read -r _ mac name_rest; do
    if [ "$(bluetoothctl info "$mac" | awk '/Connected:/ {print $2}')" = "yes" ]; then
        bt_connected+="$name_rest\n"
    fi
done < <(bluetoothctl devices)
# icon
if [ -n "$bt_connected" ]; then
    icon=""
    tooltip=$(printf "%b" "$bt_connected")
else
    icon=""
    tooltip="No devices connected"
fi
# ALWAYS produce valid JSON
printf '{"text": "%s", "tooltip": "%s"}\n' "$icon" "$tooltip"

.config/waybar/scripts/hyprscroll-overflow.sh

These are config files for waybar

#!/usr/bin/env bash
set -euo pipefail
fallback='{"text":" ","class":"hidden"}'
# Get active workspace ID
active_ws=$(hyprctl activeworkspace -j | jq '.id') || { echo "$fallback"; exit 0; }
# Get all clients on this workspace
ws_clients=$(hyprctl clients -j | jq "[.[] | select(.workspace.id==$active_ws)]")
total_clients=$(echo "$ws_clients" | jq 'length')
(( total_clients == 0 )) && { echo "$fallback"; exit 0; }
# Get all monitors
monitors=$(hyprctl monitors -j)
# Count windows that are fully inside any monitor
visible_count=$(jq -n --argjson clients "$ws_clients" --argjson monitors "$monitors" '
  [ $clients[] | select(
      ($monitors[] |
         .x <= .at[0] and (.at[0] + .size[0]) <= (.x + .width) and
         .y <= .at[1] and (.at[1] + .size[1]) <= (.y + .height)
      )
  ) ] | length
')
# Show fallback if all windows fit
if (( total_clients <= visible_count )); then
    echo "$fallback"
    exit 0
fi
# Build tooltip
tooltip=$(echo "$ws_clients" | jq -r '.[].title' | sed ':a;N;$!ba;s/\n/\\n/g')
# Output JSON
echo "{\"text\":\"★ $total_clients\",\"tooltip\":\"$tooltip\",\"class\":\"overflow\"}"

.config/waybar/scripts/hyprscroll-menu.sh

These are config files for waybar

#!/usr/bin/env bash
active_ws=$(hyprctl activeworkspace -j | jq -r '.id')
clients=$(hyprctl clients -j | jq -r \
  ".[] | select(.workspace.id==$active_ws) | \"\(.address)|\(.title)\"")
choice=$(echo "$clients" | cut -d'|' -f2 | wofi -dmenu -j -p "Windows")
[ -z "$choice" ] && exit 0
addr=$(echo "$clients" | grep "|$choice" | head -n1 | cut -d'|' -f1)
hyprctl dispatch focuswindow address:$addr

.config/waypaper/config.ini

These are config files for waypaper

[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

generated/modules/traveldroid/desktop/wayland.nix

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

generated/modules/traveldroid/desktop/xdg.nix

This sets the XDG implementation

{ lib, config, pkgs, flakeRoot, ... }:

let
  # Use the config option defaultUser directly, fallback to "henrov"
  username = config.defaultUser or "henrov";

  # Portal backends
  basePortal = pkgs.xdg-desktop-portal-gtk;    # full portal implementation
  hyprlandPortal = pkgs.xdg-desktop-portal-hyprland;  # Hyprland screencast
in
{
  #################################
  # Enable XDG desktop portals system-wide
  #################################
  xdg.portal.enable = true;

  # Base + Hyprland portals
  xdg.portal.extraPortals = [ basePortal hyprlandPortal ];

  # Map screencast interface explicitly to Hyprland
  xdg.portal.config = {
    "org.freedesktop.impl.portal.Screencast".backend = "hyprland";
  };

  #################################
  # Install portal packages system-wide
  #################################
  environment.systemPackages = [
    basePortal
    hyprlandPortal
  ];

  #################################
  # Home Manager user configuration
  #################################
  home-manager.users = {
    ${username} = {
      home.packages = [
        basePortal
        hyprlandPortal
      ];
    };
  };
}

generated/modules/traveldroid/system

generated/modules/traveldroid/system/audio.nix

{ lib, config, pkgs, ... }:

{
  ############################
  # Audio system
  ############################
  environment.systemPackages = with pkgs; [
    pulseaudio       # PulseAudio daemon
    pavucontrol      # GUI mixer
    pamixer          # CLI mixer
  ];
}

generated/modules/traveldroid/system/bluetooth.nix

{ lib, config, pkgs, home-manager, ... }:

let
  username = config.defaultUser or "henrov";
in
{
  ############################
  # Bluetooth daemon
  ############################
  hardware.bluetooth = {
    enable      = true;
    powerOnBoot = true;
    package     = pkgs.bluez;
  };
}

generated/modules/traveldroid/system/dbus.nix

This sets the dbus implementation

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

generated/modules/traveldroid/system/login-tuigreet.nix

This sets up tuigreeter which is not fancy but imo fits the aesthetic I am aiming for

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

generated/modules/traveldroid/system/networking.nix

This sets the networking.

{ 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
    pkgs.linux-firmware
  ];
}

generated/modules/traveldroid/system/nix.nix

{ lib, config, ... }:

{
    nix.settings = {
      experimental-features = [ "nix-command" "flakes" ];
      download-buffer-size = 536870912; # 512 MB
      cores = 2;
      max-jobs = 1;
    };
}

generated/modules/traveldroid/system/printing.nix

This sets the dbus implementation

{ lib, config, pkgs, ... }:

{
  ############################
  # Printing system
  ############################
  services.printing.enable = true;          # enable CUPS printing service

  ############################
  # System packages for GUI management
  ############################
  environment.systemPackages = with pkgs; [
    system-config-printer    # GUI to manage printers
  ];
}

generated/users

generated/users/henrov.nix

This is the default user, just search and replace henrov another name if you want to change

{ 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" "bluetooth" ];
  };

  #################################
  # Home Manager user definition
  #################################
  home-manager.users = {
    ${username} = {
      home.username      = username;
      home.homeDirectory = "/home/${username}";
      home.stateVersion  = "26.05";

      home.packages = [
        # add packages here
      ];

      # Activation to ensure the directory is writable
      home.activation.fixStylixPermissions = ''
        mkdir -p $HOME/.config
        chmod -R u+rwx $HOME/.config
      '';

      # Locale and timezone settings
      home.sessionVariables = {
        LANG   = "nl_NL.UTF-8";
        LC_ALL = "nl_NL.UTF-8";
        TZ     = "Europe/Amsterdam";
      };
    };
  };
}

These are all the prepared config files

.config/waybar/style.css

These are config files for .config/waybar

/* --- 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 didnt 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;
}

.config/waypaper/config.ini

These are config files for .config/waypaper

[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

.config/zed/settings.json

These are config files for .config/zed

// 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",
  },
}