# Architecture Understanding the design and structure of m3ta-nixpkgs. ## Overview m3ta-nixpkgs is organized as a modern Nix flake with a focus on reusability, consistency, and maintainability. The repository follows clear conventions and patterns to make it easy to understand, extend, and contribute to. ## Repository Structure ``` m3ta-nixpkgs/ ├── flake.nix # Main entry point, defines all outputs ├── pkgs/ # Custom packages (callPackage registry) │ ├── default.nix # Package registry (entry point) │ ├── code2prompt/ # Individual packages │ ├── hyprpaper-random/ │ ├── mem0/ │ └── ... ├── modules/ │ ├── nixos/ # NixOS modules │ │ ├── default.nix # Module aggregator │ │ ├── mem0.nix │ │ └── ports.nix │ └── home-manager/ # Home Manager modules │ ├── default.nix # Module aggregator │ ├── ports.nix │ ├── cli/ # Categorized modules │ │ ├── default.nix │ │ └── zellij-ps.nix │ └── coding/ │ ├── default.nix │ └── editors.nix ├── lib/ # Shared utilities │ ├── default.nix # Library aggregator │ └── ports.nix # Port management functions ├── shells/ # Development environments │ ├── default.nix # Shell registry │ ├── python.nix │ └── devops.nix ├── overlays/ # Package modifications │ ├── default.nix # Overlay aggregator │ └── mods/ │ └── default.nix # Individual overlays ├── templates/ # Boilerplate for new items │ ├── package/ │ ├── nixos-module/ │ └── home-manager-module/ ├── examples/ # Usage examples │ ├── nixos-configuration.nix │ └── home-manager-standalone.nix └── docs/ # Documentation ``` ## Flake Outputs `flake.nix` is the entry point that defines all outputs: ### Packages ```nix packages = forAllSystems (system: let pkgs = pkgsFor system; in import ./pkgs {inherit pkgs;}); ``` - Built for all supported systems - Uses `callPackage` pattern for lazy evaluation - Available via `nix build .#` ### Overlays ```nix overlays = { # Default overlay: adds all custom packages default = final: prev: import ./pkgs {pkgs = final;}; # Additions overlay: same as default additions = final: prev: import ./pkgs {pkgs = final;}; # Modifications overlay: modifies existing nixpkgs packages modifications = final: prev: import ./overlays/mods {inherit prev;}; }; ``` - `default`: Adds all custom packages to nixpkgs - `additions`: Individual package additions - `modifications`: Overrides existing packages ### NixOS Modules ```nix nixosModules = { default = ./modules/nixos; # Import all modules ports = ./modules/nixos/ports.nix; # Specific module mem0 = ./modules/nixos/mem0.nix; }; ``` - System-level configuration modules - Use `m3ta.*` namespace - Can import all modules or individual ones ### Home Manager Modules ```nix homeManagerModules = { default = import ./modules/home-manager; ports = import ./modules/home-manager/ports.nix; zellij-ps = import ./modules/home-manager/zellij-ps.nix; }; ``` - User-level configuration modules - Categorized by function (cli, coding) - Use `m3ta.*` namespace ### Library Functions ```nix lib = forAllSystems (system: let pkgs = pkgsFor system; in import ./lib {lib = pkgs.lib;}); ``` - Helper functions for configuration - Port management utilities - Can be used in your configurations ### Development Shells ```nix devShells = forAllSystems (system: let pkgs = pkgsFor system; in import ./shells {inherit pkgs;}); ``` - Pre-configured development environments - Available: `default`, `python`, `devops` - Usage: `nix develop .#` ### Templates ```nix templates = { package = { path = ./templates/package; description = "Template for a new package"; }; nixos-module = { path = ./templates/nixos-module; description = "Template for a new NixOS module"; }; home-manager-module = { path = ./templates/home-manager-module; description = "Template for a new Home Manager module"; }; }; ``` - Boilerplate for quick start - Usage: `nix flake init -t .#template-name` ## Package Organization ### Registry Pattern `pkgs/default.nix` acts as a central registry: ```nix { inherit (pkgs) callPackage; } rec { code2prompt = callPackage ./code2prompt {}; hyprpaper-random = callPackage ./hyprpaper-random {}; mem0 = callPackage ./mem0 {}; # ... } ``` **Benefits**: - Lazy evaluation: only builds requested packages - Consistent interface: all packages use `callPackage` - Easy discovery: one file lists all packages ### Package Structure Each package lives in its own directory: ``` pkgs/your-package/ ├── default.nix # Package definition ├── source.py # Optional: source files └── README.md # Optional: package documentation ``` **Conventions**: - Directory name matches registry attribute - Use `callPackage` for dependencies - Always include `meta` with all fields ### Common Package Patterns #### Rust Packages ```nix rustPlatform.buildRustPackage rec { pname = "myapp"; version = "1.0.0"; src = fetchFromGitHub { ... }; cargoLock.lockFile = src + "/Cargo.lock"; # ... } ``` #### Python Packages ```nix python3.pkgs.buildPythonPackage rec { pname = "mypythonapp"; version = "1.0.0"; src = fetchFromGitHub { ... }; dependencies = with python3.pkgs; [requests click]; # ... } ``` #### Shell Scripts ```nix writeShellScriptBin "myscript" '' #!/usr/bin/env bash echo "Hello World" '' ``` #### AppImage ```nix appimageTools.wrapType2 rec { name = "myapp"; src = fetchurl { ... }; # ... } ``` ## Module Organization ### NixOS Modules Located in `modules/nixos/`: ``` modules/nixos/ ├── default.nix # Imports all modules ├── ports.nix # Port management ├── mem0.nx # Individual module ``` **Pattern**: ```nix {config, lib, pkgs, ...}: with lib; let cfg = config.m3ta.myModule; in { options.m3ta.myModule = { enable = mkEnableOption "description"; # ... options }; config = mkIf cfg.enable { # ... configuration }; } ``` ### Home Manager Modules Located in `modules/home-manager/` with categories: ``` modules/home-manager/ ├── default.nix # Imports all modules ├── ports.nix # Port management ├── cli/ │ ├── default.nix # Aggregates CLI modules │ └── zellij-ps.nix └── coding/ ├── default.nix # Aggregates coding modules └── editors.nix ``` **Categories**: - `cli/`: Command-line tools and utilities - `coding/`: Development tools and editors **Pattern** (same as NixOS): ```nix {config, lib, pkgs, ...}: with lib; let cfg = config.m3ta.coding.editors; in { options.m3ta.coding.editors = { enable = mkEnableOption "editor configuration"; # ... options }; config = mkIf cfg.enable { # ... configuration }; } ``` ## Library Functions Located in `lib/`: ```nix {lib}: { # Port management utilities ports = import ./ports.nix {inherit lib;}; } ``` ### Port Management Centralized port management across hosts: ```nix # Usage in configuration portHelpers = inputs.m3ta-nixpkgs.lib.${system}.ports.mkPortHelpers myPorts; # Get port with host override services.nginx.port = portHelpers.getPort "nginx" "laptop"; # Get all ports for host allLaptopPorts = portHelpers.getHostPorts "laptop"; ``` **Benefits**: - Single source of truth for ports - Host-specific overrides - Avoid port conflicts ## Naming Conventions | Context | Convention | Example | |---------|------------|---------| | Packages | `lowercase-hyphen` | `hyprpaper-random` | | Variables | `camelCase` | `portHelpers` | | Module options | `m3ta.*` | `m3ta.ports.enable` | | Files | `lowercase-hyphen` | `my-module.nix` | | Directories | `lowercase-hyphen` | `cli/`, `coding/` | ## Code Patterns ### Module Options Always use `mkEnableOption` for enable flags: ```nix options.m3ta.myModule = { enable = mkEnableOption "description"; }; ``` ### Conditional Configuration Use `mkIf` for conditional config: ```nix config = mkIf cfg.enable { # Only applied when cfg.enable is true }; ``` ### Multiple Conditions Use `mkMerge` for multiple conditions: ```nix config = mkMerge [ (mkIf cfg.feature1.enable { ... }) (mkIf cfg.feature2.enable { ... }) ]; ``` ### Imports Multi-line, trailing commas: ```nix { lib, stdenv, fetchFromGitHub, }: ``` ### Meta Fields Always include all fields: ```nix meta = with lib; { description = "..."; homepage = "..."; license = licenses.mit; platforms = platforms.linux; mainProgram = "program-name"; }; ``` ## Design Decisions ### Flakes-Only **Decision**: Use flakes exclusively, no channels. **Rationale**: - Reproducible builds - Explicit dependencies - Better integration with modern Nix tooling ### CallPackage Pattern **Decision**: Use `callPackage` for all packages. **Rationale**: - Lazy evaluation - Clear dependency graph - Consistent interface ### Module Categorization **Decision**: Categorize Home Manager modules by function. **Rationale**: - Easier to find related modules - Logical organization - Follows user mental model ### Port Management **Decision**: Centralized port management with host overrides. **Rationale**: - Avoid port conflicts - Easy to manage multiple hosts - Single source of truth ### Namespace Convention **Decision**: Use `m3ta.*` namespace for all modules. **Rationale**: - Avoid conflicts - Clear attribution - Easy to discover ## Supported Systems - `x86_64-linux` - Primary development target - `aarch64-linux` - ARM Linux - `x86_64-darwin` - macOS Intel - `aarch64-darwin` - macOS Apple Silicon **Note**: Some packages may be Linux-only (check `meta.platforms`).