- Fix has_unique flag reading from field definition (was scanning fragment fields) - Implement duplicate validation in CLI and TUI backends - Add item counter update in Web backend after add/delete operations - Refactor Web JavaScript: remove global constants, use closure-based state per group - Store repeating group config in data-* attributes instead of global variables - Update documentation and examples with unique = true attribute - All backends now enforce unique items validation consistently
Nickel Schema to TOML Form Generation Examples
This directory contains complete, runnable examples of the TypeDialog Nickel integration workflow:
Nickel Schema → TOML Form → User Input → JSON Results → Nickel Output
Quick Start
Example 1: Simple Schema (Learning)
Generate a TOML form from a basic Nickel schema:
# Generate form
just nickel::nickel-to-form schemas/simple.ncl generated/simple/
# Execute form interactively
typedialog form generated/simple/form.toml -o results/simple_results.json
# View results
cat results/simple_results.json | jq .
What it demonstrates:
- Basic type mapping (String, Number, Bool)
- Doc comment extraction
- Default value handling
- Simple form generation
Example 2: Complex Schema (Fragmentation)
Generate fragmented forms from a schema with multiple sections:
# Generate with automatic fragmentation
just nickel::nickel-to-form schemas/complex.ncl generated/complex/
# List generated files
ls -la generated/complex/
ls -la generated/complex/fragments/
# Execute main form
typedialog form generated/complex/main_form.toml -o results/complex_results.json
What it demonstrates:
- Fragment markers (
# @fragment: name) - Multi-file form composition
- Fragment includes in main form
- Large schema organization
Generated structure:
generated/complex/
├── main_form.toml # Form with includes
└── fragments/
├── app_config.toml
├── server_config.toml
├── database_config.toml
└── cache_config.toml
Example 3: Conditional Fields (Smart Visibility)
Generate conditionals automatically from optional fields:
# Generate with conditionals
just nickel::nickel-to-form schemas/conditional.ncl generated/conditional/
# View generated conditionals
grep -A 2 'when =' generated/conditional/form.toml
# Execute form - notice conditional visibility
typedialog form generated/conditional/form.toml
What it demonstrates:
- Optional field handling
- Automatic conditional generation from contracts
- Boolean dependency detection
- Dynamic form visibility
Example generated conditionals:
[[fields]]
name = "tls_cert_path"
when = "tls_enabled == true" # Auto-generated!
[[fields]]
name = "database_url"
when = "database_enabled == true" # Auto-generated!
Example 4: i18n Extraction (Multi-Language)
Generate Fluent translation files from schema:
# Extract i18n only
just nickel::nickel-i18n schemas/i18n.ncl generated/i18n/
# View generated translations
ls -la generated/i18n/locales/
cat generated/i18n/locales/en/forms.ftl
cat generated/i18n/locales/es/forms.ftl
# Execute with Spanish locale
LOCALE=es typedialog form generated/i18n/form.toml
What it demonstrates:
- Multi-language doc comment parsing
- Fluent (.ftl) file generation
- Locale-specific form generation
- Translation key mapping
Generated translations:
# en/forms.ftl
app-name-prompt = Application name
app-name-help = Enter the application display name
# es/forms.ftl
app-name-prompt = Nombre de la aplicación
app-name-help = Ingrese el nombre de la aplicación
Example 5: Full Workflow (Schema → Results → Nickel)
Complete workflow: generate form, execute with results, render Nickel output:
# Full workflow: schema → form → results → Nickel
just nickel::nickel-workflow \
schemas/simple.ncl \
templates/config.ncl.j2 \
generated/output_config.ncl
# Validate generated Nickel
nickel typecheck generated/output_config.ncl
# View generated configuration
cat generated/output_config.ncl
What it demonstrates:
- End-to-end workflow automation
- Form execution with user input
- Template rendering with results
- Nickel validation
- Configuration generation
Directory Structure
examples/07-nickel-generation/
├── README.md # This file
├── schemas/ # Nickel schema files
│ ├── simple.ncl # Basic types only
│ ├── complex.ncl # With fragment markers
│ ├── conditional.ncl # With optional fields + boolean deps
│ └── i18n.ncl # With English/Spanish docs
├── templates/ # Jinja2 templates for rendering
│ ├── config.ncl.j2 # Basic config template
│ ├── service_spec.ncl.j2 # Kubernetes service template
│ └── deployment.ncl.j2 # Kubernetes deployment template
├── generated/ # Example outputs (reference)
│ ├── simple/
│ │ └── form.toml
│ ├── complex/
│ │ ├── main_form.toml
│ │ └── fragments/
│ ├── conditional/
│ │ └── form.toml
│ └── i18n/
│ ├── form.toml
│ └── locales/
└── results/ # Example results (reference)
└── simple_results.json
Schema Features Explained
Fragment Markers
Mark sections for automatic splitting:
# @fragment: database_config
database = { ... }
Generates separate file: fragments/database_config.toml
When to use:
- Schemas with 20+ fields
- Logical section boundaries
- Independent configuration areas
Optional Fields with Dependencies
Automatically generate conditionals:
tls_enabled | doc "Enable TLS" : Bool,
tls_cert | optional
| doc "Certificate path"
: String,
Generates:
[[fields]]
name = "tls_cert"
when = "tls_enabled == true"
Pattern: <feature>_enabled → dependent fields
Multi-Language Docs
Support multiple languages in doc comments:
field_name
| doc "English text"
| doc.es "Texto en español"
: String
Generates .ftl files for each locale with translations
Templates
config.ncl.j2
Basic application configuration template:
- Renders app metadata
- Server configuration
- Database connection (optional)
- Cache settings (conditional)
Usage:
just nickel::nickel-workflow \
schemas/simple.ncl \
templates/config.ncl.j2 \
config.ncl
service_spec.ncl.j2
Kubernetes service specification:
- Service metadata
- Port configuration
- Selector rules
- Service type (ClusterIP, NodePort, LoadBalancer)
Usage:
typedialog form <form> -o results.json
typedialog nickel-template templates/service_spec.ncl.j2 results.json -o service.ncl
nickel export service.ncl
deployment.ncl.j2
Kubernetes deployment configuration:
- Deployment metadata
- Pod replica count
- Container specification
- Resource limits and requests
- Health checks (liveness, readiness probes)
- Environment variables
Usage:
just nickel::nickel-workflow \
<schema> \
templates/deployment.ncl.j2 \
deployment.ncl
Common Workflows
Preview Form Before Generation
# Preview without writing files
just nickel::nickel-preview schemas/complex.ncl
# Then generate with full options
just nickel::nickel-to-form schemas/complex.ncl generated/complex/
Extract i18n Only
# Generate only translation files
just nickel::nickel-i18n schemas/i18n.ncl translations/
# Review translations
cat translations/locales/en/forms.ftl
cat translations/locales/es/forms.ftl
Render Template with Sample Data
# Use example results to render template
typedialog nickel-template templates/config.ncl.j2 \
results/simple_results.json \
-o sample_output.ncl
# Review output
cat sample_output.ncl
Full Interactive Workflow
# 1. Generate form
just nickel::nickel-to-form schemas/simple.ncl /tmp/form_gen/
# 2. Execute form interactively
typedialog form /tmp/form_gen/form.toml -o /tmp/results.json
# 3. Review results
cat /tmp/results.json | jq .
# 4. Render template
typedialog nickel-template templates/config.ncl.j2 \
/tmp/results.json \
-o /tmp/generated_config.ncl
# 5. Validate Nickel
nickel typecheck /tmp/generated_config.ncl
# 6. Export to JSON
nickel export /tmp/generated_config.ncl
Testing Examples
Run All Examples
#!/bin/bash
EXAMPLES_DIR="examples/07-nickel-generation"
# Test 1: Simple
echo "Testing simple schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/simple.ncl" /tmp/test_simple
[ -f /tmp/test_simple/form.toml ] && echo "✓ Simple form generated"
# Test 2: Complex
echo "Testing complex schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/complex.ncl" /tmp/test_complex
[ -f /tmp/test_complex/main_form.toml ] && echo "✓ Complex form generated"
[ -d /tmp/test_complex/fragments ] && echo "✓ Fragments created"
# Test 3: Conditional
echo "Testing conditional schema..."
just nickel::nickel-to-form "$EXAMPLES_DIR/schemas/conditional.ncl" /tmp/test_conditional
grep -q "when =" /tmp/test_conditional/form.toml && echo "✓ Conditionals generated"
# Test 4: i18n
echo "Testing i18n schema..."
just nickel::nickel-i18n "$EXAMPLES_DIR/schemas/i18n.ncl" /tmp/test_i18n
[ -f /tmp/test_i18n/locales/en/forms.ftl ] && echo "✓ English translations generated"
[ -f /tmp/test_i18n/locales/es/forms.ftl ] && echo "✓ Spanish translations generated"
echo ""
echo "All tests passed!"
Extending Examples
Adding New Schemas
- Create
schemas/my_schema.nclwith Nickel configuration - Add fragment markers (
# @fragment: name) for sections - Use optional fields for conditionals
- Use multi-language docs for i18n
{
# @fragment: my_section
my_field | doc "English" | doc.es "Español" : String,
feature_enabled | doc "Enable feature" : Bool = false,
feature_config | optional
| doc "Feature configuration"
: String,
}
Adding New Templates
- Create
templates/my_template.ncl.j2 - Use Jinja2 syntax for conditionals and loops
- Reference form result variables
- Test with sample data
{
config = {
{% for item in items %}
{{ item.name }} : String = "{{ item.value }}",
{% endfor %}
},
}
Troubleshooting
Form Generation Fails
# Verify schema syntax
nickel typecheck schemas/simple.ncl
# Check for schema-specific issues
nickel query schemas/simple.ncl
Fragment Includes Not Found
# Verify fragments directory exists
ls -la generated/complex/fragments/
# Check include paths in main form
grep includes generated/complex/main_form.toml
Conditionals Not Generated
# Verify optional fields exist
grep -A 2 "optional" schemas/conditional.ncl
# Check for boolean enable flags
grep "_enabled" schemas/conditional.ncl
i18n Not Working
# Verify locale directories created
find generated/i18n/locales/ -name "*.ftl"
# Check .ftl file format
cat generated/i18n/locales/en/forms.ftl | head
See Also
.claude/guidelines/typedialog.md- Complete TypeDialog guidetemplates/nickel/README.md- Template library documentationjust nickel::help- All available recipes/nickel-gen- Interactive slash command