Files
nixos_stuff/Droidnix (copy 1)
2026-03-17 15:38:10 +00:00
..
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00
2026-03-17 15:38:10 +00:00

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/system/
    • generated/hyprland/
    • Machine-specific configurations from assets/machines/

Generated Structure

The generated/ directory contains all generated configurations, divided into three main groups: system, hyprland, and mangowc.

System (generated/system/)

This directory contains system-wide configurations that are independent of the window manager.

Applications (applications/)

  • file_management/: Configurations for file managers and storage solutions.
  • gaming/: Settings for gaming-related software.
  • office_productivity/: Configurations for office software.
  • media_playback_editing/: Settings for media playback and editing software.
  • terminal_shell/: Configurations for terminal emulators and shells.

Development (development/)

  • databases/: Settings for local databases.
  • devops_ci_cd/: Configurations for DevOps tools.
  • programming_languages/: Settings for programming languages and their runtimes.
  • virtualization/: Configurations for virtualization and containerization tools.
  • web_development/: Settings for web development.

System Management (system_management/)

  • backups/: Settings for backup software.
  • bluetooth/: Configurations for Bluetooth devices and services.
  • power_management/: Settings for power management.
  • audio/: Configurations for audio.
  • hardware_sensors/: Settings for hardware monitoring.
  • logging_monitoring/: Configurations for system logging and monitoring.
  • login_manager/: Settings for the login manager.
  • monitor_setup/: Configurations for display settings.
  • networking/: Settings for networking.
  • printers_scanners/: Configurations for printers and scanners.
  • disk_management/: Settings for disk management.
  • security/: Security-related configurations.
  • system_updates/: Settings for system updates and package management.

Hyprland (generated/hyprland/)

This directory contains configurations specific to Hyprland.

  • animations_effects/: Settings for window animations and visual effects.
  • decorations/: Configurations for window decorations.
  • keyboard_binds/: Keyboard shortcuts for Hyprland.
  • notifications/: Settings for notifications.
  • statusbar_tray/: Configurations for the status bar and system tray.
  • task_launcher/: Settings for task launchers.
  • task_window_workspace_switcher/: Configurations for switching between windows and workspaces.
  • window_rules/: Rules for window behavior.
<<TREE>>

First Setup

  1. Clone this repository.
  2. Run the setup script: ./setup_droid.
  3. Edit .assets/system/conf/base.conf to choose your window manager (wm = "hyprland" or wm = "mangowc").
  4. Tangle this Org file to generate Nix configurations: C-c C-v t in Emacs or use this: emacs README.org --batch -f org-babel-tangle && emacs --batch --eval "(setq org-html-htmlize-output-type nil)" README.org -f org-html-export-to-html
  5. Build and switch: sudo nixos-rebuild switch --flake .#<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.

.assets/system/

This folder contains files shared across both window managers, such as wallpapers, shell configs, and system scripts.

  • conf/base.conf: Defines the window manager choice and other global settings.
  • scripts/: System-wide scripts (e.g., utilities, helpers).

.assets/hyprland/

Hyprland-specific assets, including configs, themes, and scripts.

  • conf/: Hyprland configuration files (e.g., hyprland.conf).
  • themes/: Hyprland-specific theme scripts.
  • scripts/: Hyprland-specific scripts.

.assets/mangowc/

Mangowc-specific assets, including configs, themes, and scripts.

  • conf/: Mangowc configuration files.
  • themes/: Mangowc-specific theme scripts.
  • scripts/: Mangowc-specific scripts.

.assets/machines/

Machine-specific NixOS configurations (e.g., configuration.nix for maindroid and traveldroid).

—

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";
    };
    catppuccin = {
      url = "github:catppuccin/nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    stylix = {
          url = "github:nix-community/stylix";
          inputs.nixpkgs.follows = "nixpkgs";
        };
    emacs-overlay = {
      url = "github:nix-community/emacs-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    zen-browser = {
      url = "github:youwen5/zen-browser-flake";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    hyprland.url = "github:hyprwm/Hyprland";
  };

outputs =
  inputs@{
    self,
    nixpkgs,
    home-manager,
    emacs-overlay,
    catppuccin,
    zen-browser,
    hyprland,
    stylix,
    ...
  }:
  let
    lib = nixpkgs.lib;
    system = "x86_64-linux";
    user = import ./generated/out_of_tree/users/henrov.nix;
    machines = [
      "traveldroid"
      "maindroid"
    ];
    flakeRoot = ./.; # Define flakeRoot here
  in
  {
    nixosConfigurations = lib.genAttrs machines (
      machine:
      lib.nixosSystem {
        inherit system;
        modules = [
          # Import machine-specific configurations
          ./generated/out_of_tree/machines/traveldroid/top.nix
          # Anchoring all the other nixes
          ./generated/top.nix
          # Home Manager module
          inputs.home-manager.nixosModules.home-manager
          {
            home-manager.useGlobalPkgs = true;
            home-manager.useUserPackages = true;

            home-manager.extraSpecialArgs = { inherit user inputs flakeRoot; };
          }
        ];
        specialArgs = { inherit user inputs flakeRoot; };
      }
    );

    homeConfigurations = lib.genAttrs (map (machine: "${user.username}@${machine}") machines) (
      userMachine:
      home-manager.lib.homeManagerConfiguration {
        inherit system;
        configuration = import ./user.nix { inherit inputs user flakeRoot; };
        extraSpecialArgs = { inherit user inputs flakeRoot; };
      }
    );

    devShells.${system}.default = import ./generated/out_of_tree/terminal_shell/devshell.nix {
      inherit (nixpkgs.legacyPackages.${system}) mkShell;
    };
  };
}

First the nix-files that flake really needs and that do not fit wel in the hierarchical structure

generated/out_of_tree/users/top.nix

The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure.

{ config, pkgs, lib, ... }:
{
  imports = [
    ./user.nix
  ];
}

generated/out_of_tree/users/user.nix

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

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

let
  user = import ./henrov.nix;
in
{
  home-manager.users.${user.username} = {
    home.stateVersion = "25.11";
    home.username = user.username;
    home.homeDirectory = user.homeDirectory;
    home.packages = with pkgs; [
      direnv
      git-extras
    ];
  };

  # Ensure the user is in the necessary groups
  users.users.${config.users.users.${user.username}.username} = {
    extraGroups = [ "networkmanager" ];
}

generated/out_of_tree/users/henrov.nix

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

{
  username = "henrov";
  hashedPassword = "$6$ISAmsPLyFi7idYXr$VmZsq.zMsyh1irSkyDNqtorNXG0oEHbbMVqTii1t8bymvrQ5ZQmbdi4OiBNeNYe/huHGrojXM.3TST2fTLz0T.";
  homeDirectory = "/home/henrov";
  stateVersion = "25.11";
  locale = "nl_NL.UTF-8";
}

generated/out_of_tree/terminal_shell/top.nix

This code defines a Nix shell environment (also called a "devShell") that you can enter using the nix develop command. When you enter this shell, Nix will provide the tools and dependencies listed in buildInputs.

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

{
  imports = [
    ./devshell.nix
    inputs.home-manager.nixosModules.home-manager
  ];
}

generated/out_of_tree/terminal_shell/devshell.nix

This code defines a Nix shell environment (also called a "devShell") that you can enter using the nix develop command. When you enter this shell, Nix will provide the tools and dependencies listed in buildInputs.

{ mkShell, ... }:
mkShell {
  buildInputs = with import <nixpkgs> {}; [
    nil
    nixfmt-rfc-style
  ];
}

generated/out_of_tree/machines/traveldroid/top.nix

This is the top of the machine hierarchy

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

{
  imports = [
    ./../../core/nix.nix
    ./../../core/stylix.nix
    ./../../core/gtk.nix
    ./../../core/terminal.nix
    ./boot.nix
    ./hardware-configuration.nix
    ./machine.nix
    ./dbus.nix
    ./audio.nix
    ./xdg.nix
    ./networking.nix
    inputs.home-manager.nixosModules.home-manager
  ];
}

generated/out_of_tree/machines/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/out_of_tree/machines/traveldroid/boot.nix

This file has most of the settings the control how the computer boots up.

{ pkgs, ... } :
{
  boot = {
  initrd = {
  verbose = false;   # its a lot of logs. dont need it, unless we do.
  kernelModules = [ ]; # no kernel modules on boot
  };

  extraModulePackages = [ ];       # no extra packages on boot either
  kernelPackages = pkgs.linuxPackages_latest;  # latest greatest linux kernel
  kernelParams = [ "silent" ];       # quiet those logs

  consoleLogLevel = 0;         # quiten more logs
  plymouth.enable = true;        # graphical boot animation instead

  supportedFilesystems = [ "ntfs" ];     # should see the ntfs (windows)

  loader = {
  systemd-boot.enable = true;      # systemd-boot
  systemd-boot.configurationLimit = 10;
  efi.canTouchEfiVariables = true;     # allow editing efi to edit the boot loader
  timeout = 5;           # grub timeout to make a selection
  };
  };
}

generated/out_of_tree/machines/traveldroid/machine.nix

This is the top if the machine hierarchy

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

{
  options = {
    wm = lib.mkOption {
      type = lib.types.str;
      default = "hyprland";
      description = "Type of window manager to use";
    };
  };

  config = {
    # Minimal settings that must be defined here
    networking.hostName = "traveldroid";
    wm.type = "hyprland";

    # User configuration
    users.users.${user.username} = {
      isNormalUser = true;
      extraGroups = [
        "wheel"
        "networkmanager"
      ];
      hashedPassword = user.hashedPassword;
      home = user.homeDirectory;
    };
    # Optional: Enable auto-login for testing
    #services.getty.autologinUser = user.username;
  };
}

generated/out_of_tree/machines/traveldroid/dbus.nix

This sets the dbus implementation

{ config, pkgs, lib, ... }:
{
  services.dbus = lib.mkForce {
    enable = true; # Force this to be true
  };

  # Configure dbus-broker via its configuration file
  environment.etc."dbus-broker/launch.conf".text = ''
    [General]
    LogLevel=warning
    MaxConnectionsPerUser=2048
  '';
}

generated/out_of_tree/machines/traveldroid/networking.nix

This sets the networking.

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

{
  networking = {
    useDHCP = lib.mkDefault true;
    networkmanager.enable = true;
    networkmanager.wifi.backend = "iwd";
    wireless.iwd.enable = true;
    wireless.userControlled.enable = true;
    firewall = {
      enable = true;
      # KDE Connect: discovery + encrypted connections
      allowedTCPPortRanges = [
        {
          from = 1714;
          to = 1764;
        }
      ];
      allowedUDPPortRanges = [
        {
          from = 1714;
          to = 1764;
        }
      ];
    };
  };

  # Install NetworkManager and wofi
  environment.systemPackages = with pkgs; [
    networkmanager
    wofi
  ];
}

generated/out_of_tree/machines/traveldroid/bluetooth.nix

This sets the bluetooth implementation

{ config, pkgs, ... }:
{
  # Enable Bluetooth hardware and daemon
  hardware.bluetooth = {
    enable = true;
    powerOnBoot = true;
    packages = with pkgs; [ bluez ];
  };

  # Enable Bluetooth audio support in PipeWire
  services.pipewire = {
    config.pulse = {
      bluez5.enable = true;
    };
  };

  # Optional: Additional Bluetooth settings
  hardware.bluetooth.extraConfig = ''
    AutoEnable=true
    DiscoverableTimeout=0
    PairableTimeout=0
  '';

  # Install a graphical Bluetooth manager (optional)
  environment.systemPackages = with pkgs; [
    blueman
  ];
}

generated/out_of_tree/machines/traveldroid/audio.nix

This sets audiosystem for this machine

{ config, pkgs, ... }:
{
  services.pipewire = {
    enable = true;
    alsa.enable = true;    # ALSA compatibility
    pulse.enable = true;   # PulseAudio compatibility
    wireplumber.enable = true; # Session manager for PipeWire
  };

  # Realtime privileges for pro audio (optional)
  security.rtkit.enable = true;
}

generated/out_of_tree/machines/traveldroid/xdg.nix

This sets the XDG implementation

{ config, pkgs, ... }:
{
  xdg.portal = {
    enable = true;
    config.system.default = [ "hyprland" "gtk" ];
  };
}

generated/out_of_tree/core/stylix.nix

This sets the stylix implementation

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

let
  _ = builtins.trace ("Stylix enable = " + toString config.stylix.enable) null;
in
{
  imports = [
    inputs.stylix.nixosModules.stylix
  ];

  environment.systemPackages = with pkgs; [
      feh      # wallpaper target
      #gtk3     # GTK target
     # gtk4     # GTK target
      st       # NVF / terminal target, or kitty
    ];

  stylix = {
    enable = true;
    base16Scheme = "${flakeRoot}/assets/system/theming/stylix/catppuccin-mocha.yaml";
    polarity = "dark";
  };
}

generated/out_of_tree/core/gtk.nix

Sets theming for GTK

{ config, pkgs, ... }:

{
  environment.systemPackages = with pkgs; [
      # feh      # wallpaper target
      gtk3     # GTK target
      gtk4     # GTK target
      #st       # NVF / terminal target, or kitty
    ];
  # Stylix GTK target
  stylix.targets.gtk.enable = true;
}

generated/out_of_tree/core/terminal.nix

Sets theming for the terminal

{ config, pkgs, ... }:

{
  # (NVF = Neovim/terminal flavor)
  stylix.targets.nvf.enable = true;
  # feh wallpaper integration
  stylix.targets.feh.enable = true;
}

generated/out_of_tree/core/nix.nix

I use the Catppuccin almost everywhere. The nix module integrates almost automatically everywhere (except gtk). You'll notice the color values in multiple places outside this as well.

{ config, pkgs, ... }:
{
  nix.settings = {
    extra-experimental-features = [ "nix-command" "flakes" ];
  };
}

Now we reach the top of the hierarchy which will call all other imports

generated/top.nix

The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure.

{ config, pkgs, lib, ... }:
{
  imports = [
    ./system/top.nix
    ./hyprland/top.nix
    # ./mangowc/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./hyprland.nix
    ./animations_effects/top.nix
    ./decorations/top.nix
    ./notifications/top.nix
    ./statusbar_tray/top.nix
    ./task_window_workspace_switcher/top.nix
    ./window_rules/top.nix
  ];
}

generated/hyprland/hyprland.nix

The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure.

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

let
  hyprlandFiles = builtins.attrNames (builtins.readDir "${flakeRoot}/assets/hyprland/conf/hypr");
  # Filter out hyprland.conf from the list of files to symlink
  otherHyprlandFiles = lib.filter (name: name != "hyprland.conf") hyprlandFiles;
  # Generate xdg.configFile entries for all files except hyprland.conf
  otherConfigs = lib.genAttrs otherHyprlandFiles (name: {
    target = "hypr/${name}";
    source = "${flakeRoot}/assets/hyprland/conf/hypr/${name}";
  });
in
{
  programs.hyprland = {
    enable = true;
  };

  home-manager.users.${user.username} = {
    home.stateVersion = "25.11";
    home.username = user.username;
    home.homeDirectory =
      config.home-manager.users.${user.username}.homeDirectory or "/home/${user.username}";

    wayland.windowManager.hyprland = {
      enable = true;
      settings.general."col.active_border" = lib.mkForce "0xff97cbcd 0xff89b4fa";
    };

    xdg.configFile = otherConfigs // {
      "hypr/hyprland.conf".text = ''
        ${builtins.readFile "${flakeRoot}/assets/hyprland/conf/hypr/hyprland.conf"}
      '';
      "hypr/.keep".text = "";
    };
  };
}

generated/hyprland/animations_effects/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/hyprland/decorations/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/hyprland/notifications/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/hyprland/statusbar_tray/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/hyprland/task_window_workspace_switcher/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/hyprland/window_rules/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./applications/top.nix
    ./core/top.nix
    ./development/top.nix
    ./system_management/top.nix
  ];
  # .. put any code here
}

generated/system/applications/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./packages.nix
    ./flatpaks.nix
    ./accessibility/top.nix
    ./browsing/top.nix
    ./file_management/top.nix
    ./gaming/top.nix
    ./media_playback_editing/top.nix
    ./office_productivity/top.nix
    ./terminal_shell/top.nix
  ];
  nixpkgs.config.allowUnfree = true;
}

generated/system/applications/browsing/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./zen-browser.nix
    # ./firefox.nix
    # ./vivaldi.nix
  ];
}

generated/system/applications/browsing/zen-browser.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

{ config, lib, pkgs, flakeRoot, inputs, ... }:
let
zenBrowser = inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default;
in
{
    environment.systemPackages =  [zenBrowser];
}

generated/system/applications/packages.nix

This will import all packages listed in ./assets/system/apps/packlages.conf

{ config, lib, pkgs, flakeRoot, inputs, ... }:
let
  packagesConfPath = "${flakeRoot}/assets/system/apps/packages.conf";
  raw = builtins.readFile packagesConfPath;
  # IMPORTANT: explicit "\n" so we never accidentally split into characters
  rawLines = lib.splitString "\n" raw;
  # Guard: if we accidentally split into characters, rawLines length ~= stringLength raw
  _guard = assert !(
  builtins.stringLength raw > 1 &&
  builtins.length rawLines == builtins.stringLength raw
  ); true;
  cleanLine = l:
  let
  noCR = lib.replaceStrings [ "\r" ] [ "" ] l;
  noInlineComment = lib.head (lib.splitString "#" noCR);
  in
  lib.strings.trim noInlineComment;
  entries =
  builtins.filter (l: l != "")
  (map cleanLine rawLines);
  resolvePkg = name:
  let
  parts = lib.splitString "." name;
  found = lib.attrByPath parts null pkgs;
  in
  if found == null then
    throw ''
    packages.nix: package not found in pkgs
    Token    : ${builtins.toJSON name}
    packages.conf   : ${toString packagesConfPath}
    Hint     : check the attribute name on search.nixos.org/packages
    ''
  else
    found;
  packages = builtins.seq _guard (map resolvePkg entries);
in
{
  environment.systemPackages = packages;
}

generated/system/applications/flatpaks.nix

This will import all packages listed in ./assets/system/apps/flatpaks.conf

{
  config,
  pkgs,
  lib,
  flakeRoot,
  ...
}:
let
  moduleName = "install-flatpaks";
  flatpakConfPath = "${flakeRoot}/assets/system/apps/flatpaks.conf";
  raw = builtins.readFile flatpakConfPath;
  # Explicit "\n" so we never accidentally split into characters
  rawLines = lib.splitString "\n" raw;

  # Guard: if we accidentally split into characters, rawLines length ~= stringLength raw
  _guard =
    assert !(builtins.stringLength raw > 1 && builtins.length rawLines == builtins.stringLength raw);
    true;

  cleanLine =
    l:
    let
      noCR = lib.replaceStrings [ "\r" ] [ "" ] l;
      noInlineComment = lib.head (lib.splitString "#" noCR);
    in
    lib.strings.trim noInlineComment;

  entries = builtins.filter (l: l != "") (map cleanLine rawLines);

  # Flatpak app IDs are reverse-DNS style like org.example.App (at least 2 dots).
  # We'll validate and fail early with a clear message.
  dotCount = s: builtins.length (lib.splitString "." s) - 1;

  isValidId = s: (dotCount s) >= 2; # matches the error you're seeing: "at least 2 periods"

  _validate = builtins.seq _guard (
    builtins.map (
      id:
      if isValidId id then
        true
      else
        throw ''
          ${moduleName}: invalid Flatpak ID in flatpaks.conf (needs reverse-DNS with at least 2 dots)

          Token    : ${builtins.toJSON id}
          flatpaks.conf : ${toString flatpakConfPath}

          Fix: remove stray tokens/headers, or comment them out with '#'.
        ''
    ) entries
  );

  # Use validated entries
  flatpakApps = builtins.seq _validate entries;

  syncFlatpaks = pkgs.writeShellScript "sync-flatpaks" ''
    set -euo pipefail

    # Use the deployed config path (matches environment.etc below)
    CONF="/etc/flatpak/flatpaks.conf"
    if [[ -f "$CONF" ]]; then
    echo "flatpak-sync: using $CONF"
    else
    echo "flatpak-sync: WARNING: $CONF not found, using embedded list"
    fi

    if ! flatpak remotes --system --columns=name | grep -qx flathub; then
    flatpak remote-add --system --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
    fi

    desired_apps=(
    ${lib.concatStringsSep "\n" (map (a: ''"${a}"'') flatpakApps)}
    )

    for app in "''${desired_apps[@]}"; do
    if ! flatpak info --system "$app" >/dev/null 2>&1; then
      flatpak install --system -y --noninteractive flathub "$app"
    fi
    done
  '';
in
{
  services.flatpak.enable = true;

  xdg.portal = {
    enable = true;
  };

  # Deploy the config file for runtime visibility/debugging
  environment.etc."flatpak/flatpaks.conf".source = lib.mkForce flatpakConfPath;

  systemd.services.flatpak-sync = {
    description = "Install Flatpak apps listed in flatpaks.conf";
    wantedBy = [ "multi-user.target" ];
    wants = [ "network-online.target" ];
    after = [ "network-online.target" ];

    serviceConfig = {
      Type = "oneshot";
      ExecStart = syncFlatpaks;
    };

    restartTriggers = [ flatpakConfPath ];
    path = [
      pkgs.flatpak
      pkgs.coreutils
      pkgs.gnugrep
      pkgs.gnused
    ];
  };
}

generated/system/core/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./wayland.nix
    #./eww.nix
    ./waybar.nix
    ./login-tuigreeter.nix
    #./login-lightdm.nix
    ./fonts.nix
  ];
}

generated/system/core/gtk.nix

Sewtting up GTK

{ pkgs, user, ... }:
{
  home-manager.users.${user.username} = {
    gtk = {
      enable = true;
      theme = {
        name = "Catppuccin-Mocha-Standard-Blue-Dark";
        package = pkgs.magnetic-catppuccin-gtk;
      };
      iconTheme = {
        name = "Papirus-Dark";
        package = pkgs.papirus-icon-theme;
      };
      gtk3.extraConfig = {
        gtk-application-prefer-dark-theme = 1;
      };
      gtk4.extraConfig = {
        gtk-application-prefer-dark-theme = 1;
      };
    };

  };
}

generated/system/core/fonts.nix

This file installs and configures fonts

{ config, pkgs, ... }:
{
  fonts.packages = with pkgs; [
    pkgs.nerd-fonts.iosevka
  ];
}

generated/system/core/eww.nix

This file installs and configures eww

{ lib, config, pkgs, flakeRoot, user, ... }:
let
  ewwConfigDir = "${config.home-manager.users.${user.username}.xdg.configHome}/eww";
  # Dynamically read all files in assets/system/conf/eww/
  ewwConfs = lib.genAttrs (builtins.attrNames (builtins.readDir "${flakeRoot}/assets/system/conf/eww")) (name: {
    text = builtins.readFile "${flakeRoot}/assets/system/conf/eww/${name}";
  });
in
{
  environment.systemPackages = with pkgs; [ eww ];

  home-manager.users.${user.username} = {
    home.file = {
      "${ewwConfigDir}" = {
        source = "${flakeRoot}/assets/system/conf/eww";
        recursive = true;
      };
    };

    home.sessionVariables = {
      EWW_BIN = "${pkgs.eww}/bin/eww";
    };

    # Start eww with Hyprland/MangoWC
    wayland.windowManager.hyprland.settings = lib.mkForce {
      exec-once = [ "eww daemon" ];
      exec = [ "eww open-many ${ewwConfigDir}/widgets" ]; # Adjust as needed
    };
  };
}

generated/system/core/waybar.nix

This file installs and configures waybar

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

let
  username = "henrov";
  waybar-config = pkgs.writeText "waybar-config" (builtins.readFile (flakeRoot + "/assets/system/conf/waybar/config"));
  waybar-style  = pkgs.writeText "waybar-style"  (builtins.readFile (flakeRoot + "/assets/system/conf/waybar/style.css"));
in
{
  programs.waybar = {
    enable = true;
    package = pkgs.waybar;
  };

  systemd.user.services.waybar = {
    description = "Waybar (status bar for Wayland)";
    wantedBy = [ "graphical-session.target" ];
    after = [ "graphical-session.target" ];
    serviceConfig = {
      Type = "simple";
      ExecStart = "${config.programs.waybar.package}/bin/waybar -c ${waybar-config} -s ${waybar-style}";
      Restart = "on-failure";
      RestartSec = "5s";
    };
  };

  # Create symlinks for config and style
  system.activationScripts.waybarSetup = lib.mkAfter ''
    mkdir -p /home/${username}/.config/waybar
    ln -sf ${waybar-config} /home/${username}/.config/waybar/config
    ln -sf ${waybar-style} /home/${username}/.config/waybar/style.css
    chown -R ${username}:users /home/${username}/.config/waybar
  '';
}

generated/system/core/login-tuigreeter.nix

This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder

{ pkgs, user, ... } :
{
environment.systemPackages = with pkgs; [
tuigreet
];
services.greetd = {
enable = true;
settings = {
  default_session = {
  command = pkgs.lib.mkForce "${pkgs.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'";
  };
};
};
}

generated/system/core/wayland.nix

This file sets up wayland

{ config, pkgs, lib, user, ... }:
{
  home-manager.users.${user.username} = {
    xdg.portal = {
      enable = true;
      extraPortals = with pkgs; [ xdg-desktop-portal-hyprland ];
      config.hyprland = {
        "org.freedesktop.impl.portal.Screencast" = [ "hyprland" ];
      };
    };

  home.packages = with pkgs; [
     uwsm
     ];
  };
}

generated/system/development/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./databases/top.nix
    ./devops_ci_cd/top.nix
    ./programming_languages/top.nix
    ./virtualization/top.nix
    ./web_development/top.nix
  ];
  # .. put any code here
}

generated/system/system_management/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./audio/top.nix
    ./backups/top.nix
    ./bluetooth/top.nix
    ./disk_management/top.nix
    ./hardware_sensors/top.nix
    ./logging_monitoring/top.nix
    ./login_manager/top.nix
    ./monitor_setup/top.nix
    ./networking/top.nix
    ./power_management/top.nix
    ./printers_scanners/top.nix
    ./security/top.nix
    ./system_updates/top.nix
  ];
  # .. put any code here
}

generated/system/applications/accessibility/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/applications/file_management/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./thunar.nix
  ];
}

generated/system/applications/file_management/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

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

let
  username = "henrov"; # vervang door je echte gebruikersnaam
in
{
  home-manager.users.${username} = {

       # Thunar and plugins
    home.packages = with pkgs; [
      thunar
      thunar-volman
      thunar-archive-plugin
      thunar-media-tags-plugin
      tumbler
      ffmpegthumbnailer
      gvfs
      xdg-utils
    ];

    # Default file manager
    xdg.mimeApps = {
      defaultApplications = {
        "inode/directory" = "Thunar.desktop";
      };
    };
  };
}

generated/system/applications/gaming/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/applications/media_playback_editing/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/applications/office_productivity/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/applications/terminal_shell/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./kitty.nix
    ./starship.nix
    ./zsh.nix
    ./emacs.nix
  ];
  # .. put any code here
}

generated/system/applications/terminal_shell/kitty.nix

This file sets up Kitty terminal

{ config, pkgs, lib, user, flakeRoot, ... }:
let
  kittyConf = "${flakeRoot}/assets/system/conf/kitty/kitty.conf";
  kittyTheme = "${flakeRoot}/assets/system/conf/kitty/Catppuccin-Mocha.conf";
in
{
  home-manager.users.${user.username} = {
    programs.kitty.enable = true;
    xdg.configFile."kitty/kitty.conf".source = kittyConf;
    xdg.configFile."kitty/Catppuccin-Mocha.conf".source = kittyTheme;
  };
}

generated/system/applications/terminal_shell/starship.nix

This file sets up starship prompt

{
  lib,
  config,
  pkgs,
  flakeRoot,
  ...
}:
let
  starshipConfig = lib.importTOML (flakeRoot + "/assets/system/conf/starship.toml");
in
{
  programs.starship = {
    enable = true;
    settings = starshipConfig;
  };
}

generated/system/applications/terminal_shell/zsh.nix

This sets up the zsh terminal

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

{
  # --- NixOS Configuration ---
  environment.systemPackages = with pkgs; [
    zsh
    git
    docker
  ];

  # --- Home Manager Configuration ---
  home-manager.users.henrov = {
    programs.zsh = {
      enable = true;
      enableCompletion = true;

      # Enable oh-my-zsh and use its plugins
      oh-my-zsh = {
        enable = true;
        plugins = [
          "git"
          "docker"
          "direnv"
          "zsh-autosuggestions"
          "zsh-syntax-highlighting"
          "zsh-completions"
          "zsh-history-substring-search"
        ];
        theme = "agnoster"; # Fallback, overridden below
      };

      # Source Nixpkgs-provided plugins explicitly
      initContent = ''
        # Source plugins installed by Nix
        source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
        source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
        source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh

        # Catppuccin Mocha theme for oh-my-zsh
        local mocha_base="#1E1E2E"
        local mocha_surface0="#313244"
        local mocha_text="#CDD6F4"
        local mocha_lavender="#B4BEFE"
        local mocha_blue="#89B4FA"
        local mocha_sapphire="#74C7EC"
        local mocha_teal="#94E2D5"
        local mocha_green="#A6E3A1"
        local mocha_yellow="#F9E2AF"
        local mocha_peach="#FAB387"
        local mocha_maroon="#EBA0AC"
        local mocha_red="#F38BA8"
        local mocha_mauve="#CBA6F7"
        local mocha_pink="#F5C2E7"
        local mocha_flamingo="#F2CDCD"
        local mocha_rosewater="#F5E0DC"

        # Prompt
        PROMPT='%{$fg[$mocha_blue]%}%n%{$reset_color%}@%{$fg[$mocha_peach]%}%m%{$reset_color%} %{$fg[$mocha_lavender]%}%~%{$reset_color%} %{$fg[$mocha_red]%}$%{$reset_color%} '
        RPROMPT='%{$fg[$mocha_green]%}%T%{$reset_color%}'

        # Git prompt
        ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[$mocha_yellow]%}(%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_SUFFIX="%{$fg[$mocha_yellow]%})%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[$mocha_red]%}✗%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[$mocha_green]%}✓%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_AHEAD="%{$fg[$mocha_blue]%}⇡%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_BEHIND="%{$fg[$mocha_blue]%}⇣%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[$mocha_pink]%}?%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_STAGED="%{$fg[$mocha_sapphire]%}+%{$reset_color%}"
        ZSH_THEME_GIT_PROMPT_UNSTAGED="%{$fg[$mocha_red]%}!%{$reset_color%}"

        # Virtualenv/pyenv
        ZSH_THEME_VIRTUAL_ENV_PREFIX="(%{$fg[$mocha_teal]%}"
        ZSH_THEME_VIRTUAL_ENV_SUFFIX="%{$reset_color%})"

        # Right prompt with Git status
        RPROMPT='$(git_prompt_info) %{$fg[$mocha_green]%}%T%{$reset_color%}'

        # Set the custom theme
        ZSH_THEME="catppuccin-mocha"
      '';
    };

    # Home Manager packages (optional)
    home.packages = with pkgs; [
      direnv
      git-extras
    ];
  };
}

generated/system/applications/terminal_shell/emacs.nix

This sets up the emacs terminal

{ pkgs, ... }:

{
  # NixOS Configuration
  environment.systemPackages = with pkgs; [
    # Add system-wide packages here, if any
  ];

  # Home Manager Configuration for the user 'henrov'
  home-manager.users.henrov = {
    programs.emacs = {
      enable = true;
      package = pkgs.emacs-pgtk.override { withTreeSitter = true; };

      # Group related packages for clarity and easier maintenance
      extraPackages = epkgs: with epkgs; [
        # Tree-sitter and language support
        manualPackages.treesit-grammars.with-all-grammars
        rust-mode
        rustic
        nix-mode
        hcl-mode

        # UI/UX and navigation
        nerd-icons
        doom-modeline
        diminish
        eldoc
        eldoc-box
        pulsar
        which-key
        avy
        consult
        vertico
        marginalia
        crux
        shell-pop

        # Completion and snippets
        nerd-icons-corfu
        corfu
        cape
        orderless
        yasnippet
        yasnippet-snippets

        # Utilities and tools
        rg
        exec-path-from-shell
        eat
        f
        gptel
        nixpkgs-fmt
        envrc

        # Theming
        catppuccin-theme

        # Git
        magit

        # Editing and workflow
        expreg
        vundo
        puni

        # Error and side panel support
        sideline
        sideline-flymake
        sideline-eglot
      ];
    };

    # Home Manager session variables
    home.sessionVariables = {
      EDITOR = "emacs";
      XDG_SCREENSHOTS_DIR = "~/screenshots";
    };
  /*
    # Home Manager file management
    home.file = {
      "emacs/early-init.el" = {
        source = ./early-init.el;
        target = ".emacs.d/early-init.el";
      };
      "emacs/init.el" = {
        source = ./init.el;
        target = ".emacs.d/init.el";
      };
    };
  */
  };
}

generated/system/applications/terminal_shell/early-init.el

This helps set up the emacs terminal

;;; 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/system/applications/terminal_shell/init.el

This helps set up the emacs terminal

;;; 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/system/development/databases/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/development/devops_ci_cd/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/development/programming_languages/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/development/virtualization/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/development/web_development/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/audio/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/backups/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/bluetooth/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/disk_management/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/hardware_sensors/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/logging_monitoring/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/login_manager/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/monitor_setup/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/networking/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/power_management/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/printers_scanners/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/security/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/system_management/system_updates/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    # No subfolders to import
  ];
  # .. put any code here
}

generated/system/task_launcher/top.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

{ config, pkgs, lib, user, inputs, flakeRoot,... }:
{
  imports = [
    ./wofi.nix
  ];
  # .. put any code here
}

generated/system/task_launcher/wofi.nix

This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder

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

let
  wofiConfigDir = "${config.home-manager.users.${user.username}.xdg.configHome}/wofi";
  # Dynamically read all files in assets/hyprland/conf/wofi/
  wofiConfs =
    lib.genAttrs (builtins.attrNames (builtins.readDir "${flakeRoot}/assets/system/conf/wofi"))
      (name: {
        text = builtins.readFile "${flakeRoot}/assets/system/conf/wofi/${name}";
      });
in
{
  environment.systemPackages = with pkgs; [
    wofi
  ];

  home-manager.users.${user.username} = {
    home.file = {
      # Map the files to their target paths in ~/.config/wofi/
      "${wofiConfigDir}/config" = wofiConfs."wofi.conf"; # Use the actual filename
      "${wofiConfigDir}/style.css" = wofiConfs."theming.css"; # Use the actual filename
    };

    home.sessionVariables = {
      WOFI_CONFIG = "${wofiConfigDir}/config";
      WOFI_STYLE = "${wofiConfigDir}/style.css";
    };
  };
}