Documentation
Use ndg for modules, nixdoc-style comments for functions, and helpful error messages with clear explanations and examples.
Documentation
Module Documentation
Use ndg for modules. Every option gets a description:
options.weyl.services.apiServer = { enable = mkOption { type = types.bool; default = false; description = '' Whether to enable the Weyl API server.
Configures a systemd service with automatic restart and opens the configured port in the firewall. ''; example = true; };};Package Documentation
Use nixdoc-style comments for functions:
/** Build a Weyl ML model package.
This builder handles model optimization, quantization, and runtime selection for deployment. It automatically selects the appropriate backend based on the target runtime.
# Arguments
name : Model package name, used in the Nix store path
modelFile : Path to the source model file (ONNX, PyTorch, or TensorFlow format)
runtime : Target inference runtime. One of "onnx", "pytorch", or "tensorflow"
# Examples
Build a simple ONNX model:
```nix buildMlModel { name = "sentiment-classifier"; modelFile = ./models/sentiment.onnx; runtime = "onnx"; } ```
Build with CUDA support:
```nix buildMlModel { name = "image-classifier"; modelFile = ./models/resnet.pt; runtime = "pytorch"; cudaSupport = true; } ```*/buildMlModel = { name, modelFile, runtime, cudaSupport ? false, ... }: ...Inline Comments: Use Sparingly
Prefer module docs, meta.description, and nixdoc comments. When inline comments are necessary, explain why, not what:
# Bad: Obvious from the code# Set port to 8080port = 8080;
# Good: Explains non-obvious reasoning# nvidia 535 has memory leak with our workloads, pin to 530nvidia.package = config.boot.kernelPackages.nvidiaPackages.legacy_530;Error Messages
Error messages should explain what went wrong, why it’s wrong, and how to fix it:
# Uselessassertions = [{ assertion = cfg.port > 0; message = "port must be positive";}];
# Helpfulassertions = [{ assertion = cfg.port > 0 && cfg.port <= 65535; message = '' weyl.services.database.connection.port: Invalid port ${toString cfg.port}
Port must be between 1 and 65535.
Common database ports: - PostgreSQL: 5432 - MySQL: 3306 - Redis: 6379
Example fix: weyl.services.database.connection.port = 5432; '';}];Yes, it’s verbose. When someone hits this at 2am during an incident, they’ll know exactly what’s wrong and how to fix it.
Assertion Hierarchy
NixOS assertions - User-facing configuration validation:
assertions = [{ assertion = cfg.tls.enable -> (cfg.tls.certificate != null); message = '' weyl.services.apiServer: TLS enabled but no certificate provided.
Either provide a certificate: weyl.services.apiServer.tls.certificate = /path/to/cert.pem;
Or disable TLS: weyl.services.apiServer.tls.enable = false; '';}];lib.assertMsg - Internal invariants:
lib.assertMsg (cfg.package ? meta.mainProgram) "weyl.services.apiServer.package must define meta.mainProgram"builtins.addErrorContext - Adding context to complex evaluation:
processConfig = config: builtins.addErrorContext "while processing weyl.services.api configuration" ( # ... );Debugging
builtins.trace and lib.traceVal are for debugging only. Remove them before committing:
# DEVELOPMENT ONLY - remove before PRlet debugValue = lib.traceVal config.weyl.services;in