Add contract parsing, i18n extraction, template rendering, and roundtrip support for Nickel. Update backends and form parser for integration. Add testing and build infrastructure.
Nickel Template Library
Reutilizable template library for generating Nickel configuration schemas from TypeDialog forms.
Structure
Fields (fields/)
Basic field templates for different data types. Each template generates a single field definition.
- string_field.ncl.j2 - String field with optional doc and contract
- number_field.ncl.j2 - Number field with validation
- boolean_field.ncl.j2 - Boolean flag field
- optional_field.ncl.j2 - Optional field wrapper (any type)
- enum_field.ncl.j2 - Enumerated field with predefined options
Forms (forms/)
Complete schema templates for specific use cases. Each generates a full configuration structure.
- config_schema.ncl.j2 - General application configuration
- service_spec.ncl.j2 - Kubernetes service specification
- deployment.ncl.j2 - Deployment configuration with environment and health checks
Macros (macros/)
Reusable macro definitions for common patterns.
- contracts.ncl.j2 - Validation contract definitions (NonEmpty, port ranges, etc.)
- validation.ncl.j2 - Predicate macros (length, range, etc.)
- metadata.ncl.j2 - Documentation and type annotation helpers
Usage
Field Templates
Use in form templates with Tera include syntax:
{% include "fields/string_field.ncl.j2" with {
name: "app_name",
doc: "Application name",
contract: "std.string.NonEmpty",
default: "myapp"
} %}
Form Templates
Render a complete schema:
typedialog nickel-template forms/config_schema.ncl.j2 form_results.json -o config.ncl
Macro Templates
Include macros in custom templates:
{% include "macros/contracts.ncl.j2" %}
{% include "macros/validation.ncl.j2" %}
Then use the defined macros:
{{ non_empty_string("username", "User login name") }}
{{ port_number("server_port", "HTTP port") }}
Template Context Variables
Templates expect the following context from form results:
{
"name": "field_name",
"doc": "field description",
"contract": "std.string.NonEmpty",
"default": "default_value",
"field_type": "String|Number|Bool",
"options": ["option1", "option2"],
"groups_by_section": { "section_name": [...fields...] }
}
Examples
Simple Configuration Schema
Create a form with fields for app name, version, and debug mode:
[[fields]]
name = "app_name"
type = "text"
prompt = "Application name"
required = true
[[fields]]
name = "app_version"
type = "text"
prompt = "Version"
default = "1.0.0"
[[fields]]
name = "debug_mode"
type = "confirm"
prompt = "Enable debug mode"
Render with template:
typedialog nickel-template forms/config_schema.ncl.j2 results.json -o config.ncl
Output:
{
app = {
name | doc "Application name" : String = "myapp",
version | doc "Version" : String = "1.0.0",
debug_mode | doc "Enable debug mode" : Bool = true,
},
}
Service Specification
Use for Kubernetes or containerized deployments:
typedialog form forms/service_spec.ncl.j2 \
-o service_results.json
typedialog nickel-template forms/service_spec.ncl.j2 \
service_results.json -o service.ncl
nickel export service.ncl
Extending
Create new templates following these conventions:
- Single-field templates →
fields/{type}_field.ncl.j2 - Schema templates →
forms/{purpose}_schema.ncl.j2 - Macro libraries →
macros/{category}.ncl.j2
All templates use Jinja2 syntax. Refer to Tera documentation for available filters and functions.
Best Practices
- Use meaningful variable names in templates
- Document required context variables with comments
- Keep templates DRY by using macros for common patterns
- Validate generated Nickel with
nickel typecheck - Version templates with your forms for consistency