My repo serves as an educational example showing how den and my related libs structure a Dendritic NixOS setup with named, composable aspects instead of file imports. This is just one of many possible ways to organize a dendritic implementation. Feel free to explore, and share how you do things.
This specific setup is powered by den · flake-aspects · denful · flake-file · import-tree · flake-parts
--
# Traditional imports # Dendritic aspects
imports = [ vix.nargun.includes = [
./hardware.nix vix.hardware
../../shared/desktop.nix vix.niri-desktop
]; ];Aspects are named values, not file paths. They compose without relative path juggling.
modules/
├── dendritic.nix # Bootstraps dendritic libs
├── community/vix.nix # Creates vix.* namespace
├── hosts.nix # Declares hosts, wires default profiles
├── community/
│ └── profile.nix # Defines host-profile and user-profile hooks
├── hosts/
│ └── nargun.nix # Composes aspects for nargun host
└── vic/
└── common-host-env.nix # Composes user environment aspects
1. Custom Namespace (vix.nix)
den.aspects.vix.provides = { }; # you can also use flake.aspects to expose all to flake.modules.
flake.vix = config.den.aspects.vix.provides; # I just want to expose the vix aspect tree.
_module.args.vix = config.den.aspects.vix.provides;Creates vix.* namespace. Everything under vix belongs to this config.
The vix namespace is written to directly, and read from module args, it is also shared as a flake output.
Meaning other people can do _module.args.vix = inputs.vix.vix, and re-use modules from this repository's community/ exactly as they are. Adopting a namespace for your aspects allows re-use for people using import-tree to load files from community repos.
2. Central Host Declaration (hosts.nix)
den.hosts.x86_64-linux.nargun.users.vic = { };
den.default.host._.host.includes = [ vix.host-profile ];
den.default.user._.user.includes = [ vix.user-profile ];All hosts declared here. Default profiles automatically applied to every host/user.
3. Dynamic Profile Routing (profile.nix)
vix.host-profile = { host }: {
# access host profile from vix, many modules can contribute to the same aspect.
includes = [ vix.${host.name} ];
};
vix.user-profile = { host, user }: {
# users can enhance the host they are part of, by providing aspects to it.
includes = [ (vix.${user.name}._.common-host-env { inherit host user; }) ];
};Profiles select aspects by host/user name. vix.nargun wired automatically for nargun host.
4. Aspect Composition with Variants (nargun.nix)
vix.nargun.provides = {
base.includes = [ vix.dev-laptop ];
hw.includes = [ vix.kvm-amd vix.niri-desktop ];
};
vix.nargun.includes = [ vix.nargun._.base vix.nargun._.hw ];
vix.nargun-vm.includes = [ vix.nargun._.base vix.nargun._.vm ];Sub-aspects via provides.X become _.X. Hardware and VM share base.
5. User Environment Assembly (common-host-env.nix)
vix.vic._.common-host-env = { host, user }: {
includes = map (f: f { inherit host user; }) [
vix.vic.provides.admin
vix.vic.provides.fish
// ... more aspects
];
};User profile calls this with context. Each aspect receives { host, user }.
6. Multi-Class Aspects (fish.nix)
vix.vic.provides.fish = { user, ... }: {
nixos.users.users.${user.userName}.shell = pkgs.fish;
homeManager.programs.fish.enable = true;
};Single aspect configures both system and home-manager.
dendritic.nixloads dendritic libsvix.nixcreates namespace (vix.*)hosts.nixdeclares hosts and wires profiles:den.hosts.x86_64-linux.nargun.users.vic = { }- Every host includes
vix.host-profile - Every user includes
vix.user-profile
profile.nixroutes by name:vix.host-profile→vix.${host.name}(e.g.,vix.nargun)vix.user-profile→vix.${user.name}._.common-host-env
nargun.nixcomposes host aspectscommon-host-env.nixcomposes user aspects
Result: Declare a host in one place, everything wires automatically via naming convention.
Follow the flow above, then explore:
fish.nix- Simple parametric aspectunfree.nix- Aspect factory patternvm.nix- Package system as VM:nix run github:vic/vix/den#vm
-
Named aspects instead of manual imports.
-
Functional Composition instead of Duplication.
-
Parameters intead of Hardcoding.
-
Sharing instead of Copy+Pasting.