> ## Documentation Index
> Fetch the complete documentation index at: https://soriphoono-homelab.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Creating Custom Modules

> Learn how to create reusable NixOS and Home Manager modules

This guide covers creating custom modules for your homelab infrastructure. Modules are the building blocks that make your configuration reusable and maintainable.

## Module Structure

Modules in this homelab are organized by scope:

* `modules/nixos/` - System-level NixOS modules
* `modules/home/` - User-level Home Manager modules
* `modules/droid/` - Nix-on-Droid modules

Each category is further organized by function:

```
modules/nixos/
├── core/           # Essential system functionality
├── desktop/        # Desktop environments and features
└── hosting/        # Server and hosting capabilities

modules/home/
├── core/           # Essential user configuration
└── userapps/       # User applications
```

## Creating a Module

**1. Create Issue**

Follow the Issue-First policy:

```bash theme={null}
# Create issue: "feat: add bluetooth module for hardware support"
```

**2. Create Feature Branch**

```bash theme={null}
git checkout -b dev-add-bluetooth-module
```

**3. Choose Module Location**

Decide where your module belongs based on its scope:

* System hardware? → `modules/nixos/core/hardware/`
* Desktop feature? → `modules/nixos/desktop/features/`
* User application? → `modules/home/userapps/`

**4. Create Module File**

Create a new `.nix` file in the appropriate directory:

```bash theme={null}
touch modules/nixos/core/hardware/bluetooth.nix
```

**5. Write Module Code**

Follow the standard module pattern:

```nix modules/nixos/core/hardware/bluetooth.nix theme={null}
{
  lib,
  config,
  pkgs,
  ...
}: let
  cfg = config.core.hardware.bluetooth;
in {
  options.core.hardware.bluetooth = {
    enable = lib.mkEnableOption "Enable bluetooth hardware support";
    
    # Additional options
    powerOnBoot = lib.mkOption {
      type = lib.types.bool;
      default = true;
      description = "Power on bluetooth adapter on boot";
    };
  };

  config = lib.mkIf cfg.enable {
    hardware.bluetooth = {
      enable = true;
      powerOnBoot = cfg.powerOnBoot;

      settings = {
        General = {
          Experimental = true;
          Enable = "Source,Sink,Media,Socket";
        };
      };
    };
    
    # Optional: Add packages
    environment.systemPackages = with pkgs; [
      bluez
    ];
  };
}
```

**6. Register Module**

Add your module to the appropriate `default.nix` file:

```nix modules/nixos/core/hardware/default.nix theme={null}
{
  imports = [
    ./bluetooth.nix
    ./adb.nix
    ./gpu
    ./hid
  ];
}
```

**7. Validate Module**

Test that your module compiles:

```bash theme={null}
nix flake check
```

**8. Commit Changes**

Use conventional commits:

```bash theme={null}
git add modules/nixos/core/hardware/bluetooth.nix
git commit -m "feat: add bluetooth hardware module"
```

## Module Patterns

### Basic Enable Module

Simplest form - just an enable option:

```nix theme={null}
{
  lib,
  config,
  ...
}: let
  cfg = config.desktop.features.gaming;
in {
  options.desktop.features.gaming = {
    enable = lib.mkEnableOption "Enable steam integration";
  };

  config = lib.mkIf cfg.enable {
    environment.systemPackages = with pkgs; [
      moonlight-qt
    ];
  };
}
```

### Module with Options

Add configuration options:

```nix theme={null}
{
  lib,
  config,
  ...
}: let
  cfg = config.core.secrets;
in {
  options.core.secrets = {
    enable = lib.mkEnableOption "Enable the core secrets module";

    defaultSopsFile = lib.mkOption {
      type = lib.types.nullOr lib.types.path;
      default = null;
      description = ''
        The default secrets file to use for the secrets module.
        This is used when no specific secrets file is provided.
      '';
      example = ./secrets.yaml;
    };
  };

  config = lib.mkIf cfg.enable {
    sops.defaultSopsFile = lib.mkIf (cfg.defaultSopsFile != null) cfg.defaultSopsFile;
  };
}
```

### Nested Module Structure

For complex features, use nested modules:

```
modules/nixos/desktop/environments/
├── default.nix
├── kde.nix
├── cosmic.nix
├── display_managers/
│   ├── default.nix
│   ├── sddm.nix
│   └── greetd/
│       └── default.nix
└── managers/
    ├── default.nix
    └── hyprland.nix
```

### Home Manager Module

User-level modules follow similar patterns:

```nix theme={null}
{
  lib,
  config,
  pkgs,
  ...
}: let
  cfg = config.userapps.browsers.firefox;
in {
  options.userapps.browsers.firefox = {
    enable = lib.mkEnableOption "Enable Firefox browser";
  };

  config = lib.mkIf cfg.enable {
    programs.firefox = {
      enable = true;
      # Additional Firefox configuration
    };
  };
}
```

## Module Best Practices

> **Naming Conventions**
>
> * Use descriptive, lowercase names
> * Separate words with hyphens in filenames: `bluetooth.nix`, `network-manager.nix`
> * Use dot notation in option paths: `core.hardware.bluetooth`

> **Option Design**
>
> * Always use `lib.mkEnableOption` for boolean enables
> * Provide sensible defaults
> * Include descriptions for all options
> * Add example values where helpful
> * Use proper types: `lib.types.str`, `lib.types.int`, `lib.types.path`, etc.

> **Configuration Organization**
>
> * Group related configuration together
> * Use `let ... in` for computed values
> * Keep `config` section clean and readable
> * Use `lib.mkIf` to conditionally apply configuration

> **Dependencies**
>
> * Declare module inputs: `lib`, `config`, `pkgs`
> * Import other modules through `default.nix` files
> * Avoid circular dependencies

## Testing Your Module

### Local Testing

Test on a system configuration:

```nix systems/test-system/default.nix theme={null}
{
  core.hardware.bluetooth.enable = true;
}
```

### Flake Checks

Ensure it passes validation:

```bash theme={null}
nix flake check
```

### Manual Validation

Build the configuration:

```bash theme={null}
nix build .#nixosConfigurations.test-system.config.system.build.toplevel
```

## Common Module Types

### Hardware Module

Enables hardware support:

```nix theme={null}
core.hardware.bluetooth.enable = true;
core.hardware.gpu.dedicated.nvidia.enable = true;
```

### Service Module

Configures system services:

```nix theme={null}
core.networking.tailscale.enable = true;
core.networking.openssh.enable = true;
```

### Application Module

Installs and configures applications:

```nix theme={null}
userapps.browsers.firefox.enable = true;
userapps.development.editors.vscode.enable = true;
```

## Next Steps

* [Add your module to a system](https://soriphoono-homelab.mintlify.site/guides/adding-new-system.md)
* [Set up secrets for your module](https://soriphoono-homelab.mintlify.site/guides/managing-secrets.md)
* [Contribute your module](https://soriphoono-homelab.mintlify.site/guides/contributing.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.