# Templates Jinja2 and Nickel templates for configuration and deployment generation. ## Purpose Templates provide: - **Nickel output generation** - Jinja2 templates for TypeDialog nickel-roundtrip - **Docker Compose generation** - Infrastructure-as-code for containerized deployment - **Kubernetes manifests** - Declarative deployment manifests - **TOML export** - Service configuration generation for Rust codebase ## File Organization ``` templates/ ├── README.md # This file ├── orchestrator-config.ncl.j2 # Nickel output template (Jinja2) ├── control-center-config.ncl.j2 # Nickel output template (Jinja2) ├── mcp-server-config.ncl.j2 # Nickel output template (Jinja2) ├── installer-config.ncl.j2 # Nickel output template (Jinja2) ├── docker-compose/ # Docker Compose templates │ ├── platform-stack.solo.yml.ncl │ ├── platform-stack.multiuser.yml.ncl │ ├── platform-stack.cicd.yml.ncl │ └── platform-stack.enterprise.yml.ncl ├── kubernetes/ # Kubernetes templates │ ├── orchestrator-deployment.yaml.ncl │ ├── orchestrator-service.yaml.ncl │ ├── control-center-deployment.yaml.ncl │ ├── control-center-service.yaml.ncl │ └── platform-ingress.yaml.ncl └── configs/ # Service config templates (optional) ├── orchestrator-config.toml.ncl ├── control-center-config.toml.ncl └── mcp-server-config.toml.ncl ``` ## Jinja2 Config Templates **Critical for TypeDialog nickel-roundtrip workflow**: ```bash typedialog-web nickel-roundtrip "$CONFIG" "forms/{service}-form.toml" --output "$CONFIG" --template "templates/{service}-config.ncl.j2" ``` ### Template Pattern: orchestrator-config.ncl.j2 ```nickel # Orchestrator Configuration - Nickel Format # Auto-generated by provisioning TypeDialog # Edit via: nu scripts/configure.nu orchestrator {mode} { orchestrator = { # Workspace Configuration workspace = { {%- if workspace_name %} name = "{{ workspace_name }}", {%- endif %} {%- if workspace_path %} path = "{{ workspace_path }}", {%- endif %} {%- if workspace_enabled is defined %} enabled = {{ workspace_enabled | lower }}, {%- endif %} {%- if multi_workspace is defined %} multi_workspace = {{ multi_workspace | lower }}, {%- endif %} }, # Server Configuration server = { {%- if server_host %} host = "{{ server_host }}", {%- endif %} {%- if server_port %} port = {{ server_port }}, {%- endif %} {%- if server_workers %} workers = {{ server_workers }}, {%- endif %} {%- if server_keep_alive %} keep_alive = {{ server_keep_alive }}, {%- endif %} }, # Storage Configuration storage = { {%- if storage_backend %} backend = '{{ storage_backend }}, {%- endif %} {%- if storage_path %} path = "{{ storage_path }}", {%- endif %} {%- if surrealdb_url %} surrealdb_url = "{{ surrealdb_url }}", {%- endif %} }, # Queue Configuration queue = { {%- if max_concurrent_tasks %} max_concurrent_tasks = {{ max_concurrent_tasks }}, {%- endif %} {%- if retry_attempts %} retry_attempts = {{ retry_attempts }}, {%- endif %} {%- if retry_delay %} retry_delay = {{ retry_delay }}, {%- endif %} {%- if task_timeout %} task_timeout = {{ task_timeout }}, {%- endif %} }, # Monitoring Configuration (optional) {%- if enable_monitoring is defined and enable_monitoring %} monitoring = { enabled = true, {%- if metrics_interval %} metrics_interval = {{ metrics_interval }}, {%- endif %} {%- if health_check_interval %} health_check_interval = {{ health_check_interval }}, {%- endif %} }, {%- endif %} }, } ``` ### Key Jinja2 Patterns **Conditional blocks** (only include if field is set): ```nickel {%- if workspace_name %} name = "{{ workspace_name }}", {%- endif %} ``` **String values** (with quotes): ```nickel {%- if storage_backend %} backend = '{{ storage_backend }}, # Enum (atom syntax) {%- endif %} ``` **Numeric values** (no quotes): ```nickel {%- if server_port %} port = {{ server_port }}, # Number {%- endif %} ``` **Boolean values** (lower case): ```nickel {%- if workspace_enabled is defined %} enabled = {{ workspace_enabled | lower }}, # Boolean (true/false) {%- endif %} ``` **Comments** (for generated files): ```nickel # Auto-generated by provisioning TypeDialog # Edit via: nu scripts/configure.nu orchestrator {mode} ``` ## Docker Compose Templates Nickel templates that import from `values/*.ncl`: ```nickel # templates/docker-compose/platform-stack.solo.yml.ncl # Docker Compose Platform Stack - Solo Mode # Imports config from values/orchestrator.solo.ncl let orchestrator_config = import "../../values/orchestrator.solo.ncl" in let control_center_config = import "../../values/control-center.solo.ncl" in { version = "3.8", services = { orchestrator = { image = "provisioning-orchestrator:latest", container_name = "orchestrator", ports = [ "%{std.to_string orchestrator_config.orchestrator.server.port}:9090", ], environment = { ORCHESTRATOR_SERVER_HOST = orchestrator_config.orchestrator.server.host, ORCHESTRATOR_SERVER_PORT = std.to_string orchestrator_config.orchestrator.server.port, ORCHESTRATOR_STORAGE_BACKEND = orchestrator_config.orchestrator.storage.backend, }, volumes = [ "./data/orchestrator:%{orchestrator_config.orchestrator.storage.path}", ], restart = "unless-stopped", }, control-center = { image = "provisioning-control-center:latest", container_name = "control-center", ports = [ "%{std.to_string control_center_config.control_center.server.port}:8080", ], environment = { CONTROL_CENTER_SERVER_HOST = control_center_config.control_center.server.host, CONTROL_CENTER_SERVER_PORT = std.to_string control_center_config.control_center.server.port, }, restart = "unless-stopped", }, }, } ``` ### Rendering Docker Compose ```bash # Export Nickel template to YAML nickel export --format json templates/docker-compose/platform-stack.solo.yml.ncl | yq -P > docker-compose.solo.yml ``` ## Kubernetes Templates Nickel templates for Kubernetes manifests: ```nickel # templates/kubernetes/orchestrator-deployment.yaml.ncl let config = import "../../values/orchestrator.solo.ncl" in { apiVersion = "apps/v1", kind = "Deployment", metadata = { name = "orchestrator", labels = { app = "orchestrator", }, }, spec = { replicas = 1, selector = { matchLabels = { app = "orchestrator", }, }, template = { metadata = { labels = { app = "orchestrator", }, }, spec = { containers = [ { name = "orchestrator", image = "provisioning-orchestrator:latest", ports = [ { containerPort = 9090, }, ], env = [ { name = "ORCHESTRATOR_SERVER_PORT", value = std.to_string config.orchestrator.server.port, }, { name = "ORCHESTRATOR_STORAGE_BACKEND", value = config.orchestrator.storage.backend, }, ], volumeMounts = [ { name = "data", mountPath = config.orchestrator.storage.path, }, ], }, ], volumes = [ { name = "data", persistentVolumeClaim = { claimName = "orchestrator-pvc", }, }, ], }, }, }, } ``` ## Rendering Templates ### Render to JSON ```bash nickel export --format json templates/orchestrator-config.ncl.j2 > config.json ``` ### Render to YAML (via yq) ```bash nickel export --format json templates/kubernetes/orchestrator-deployment.yaml.ncl | yq -P > deployment.yaml ``` ### Render to TOML ```bash nickel export --format toml templates/configs/orchestrator-config.toml.ncl > config.toml ``` ## Template Variables Variables in templates come from: 1. **Form values** (TypeDialog input) 2. **Imported configs** (Nickel imports) 3. **Constraint interpolation** (constraints.toml) ## Best Practices 1. **Use conditional blocks** - Only include fields if set 2. **Import configs** - Reuse Nickel configs in templates 3. **Type conversion** - Use `std.to_string` for numeric values 4. **Comments** - Explain generated/auto-edited markers 5. **Validation** - Use `nickel typecheck` to verify templates 6. **Environment variables** - Prefer env over hardcoding ## Template Testing ```bash # Typecheck Jinja2 + Nickel template nickel typecheck templates/orchestrator-config.ncl.j2 # Evaluate and view output nickel eval templates/orchestrator-config.ncl.j2 # Export and validate output nickel export --format json templates/orchestrator-config.ncl.j2 | jq '.' ``` ## Adding a New Template 1. **Create template file** (`{service}-config.ncl.j2` or `{name}.yml.ncl`) 2. **Define structure** (Nickel or Jinja2) 3. **Import configs** (if Nickel) 4. **Use variables** (from forms or imports) 5. **Typecheck**: `nickel typecheck templates/{file}` 6. **Test rendering**: `nickel export {format} templates/{file}` --- **Version**: 1.0.0 **Last Updated**: 2025-01-05