Technical positioning and internal architecture of TypeDialog.
## Positioning
TypeDialog is not a terminal prompt library — it is a **form orchestration layer** that sits two abstraction levels above tools like Inquire, Ratatui, or Axum.
The comparison point is relevant: Inquire (`inquire = "0.9"`) is one of TypeDialog's dependencies, consumed as the render engine for the CLI backend. A user of TypeDialog never calls `Text::new("Name?").prompt()` directly — that call happens inside `InquireBackend::execute_field_sync`, invisible to the form author.
**Unified schema** — a single Nickel (`.ncl`) or TOML file describes the same form for CLI, TUI, and HTTP. No per-backend code. See [ADR-001](./adr/adr-001-nickel-form-definition.md).
**Nushell as integration runtime** — outputs flow as structured data into Nu pipelines via the Nushell plugin protocol (`nu-plugin = "0.110.0"`), not as text.
**AI backend** (`typedialog-ai` + `typedialog-agent`) — forms can be generated or processed by agents backed by SurrealDB (`kv-mem`), Tantivy full-text search, and HNSW vector search (`instant-distance`).
**Native i18n** — Fluent bundles with system locale detection, no external tooling required.
`.ncl` forms are loaded via `nickel export --format json` as a subprocess. If the export fails for any reason — contract violation, syntax error, missing import — the process aborts before any interaction begins. TOML forms are deserialized directly via `serde`.
Fragment lazy-loading (`includes:` in TOML groups) is replaced by Nickel native imports. `build_element_list` is now a pure in-memory operation with no I/O. The functions `expand_includes` and `load_fragment_form` remain available in `fragments.rs` as rescue code.
### `when_false` — Conditional Field Output
Fields with a `when:` condition that evaluates to false are skipped by default. `when_false = "default"` instructs the executor to inject the field's `default` value into results even when the condition is false:
```toml
[fields.tls_cert_path]
when = "tls_enabled == true"
when_false = "default"
default = "/etc/ssl/cert.pem"
```
This ensures Nickel roundtrip writers always have a value for every schema field regardless of which branches the user navigated.
`execute_form_complete` has a default implementation that delegates to `execute_field` sequentially. Backends that need full-form rendering (TUI, Web) override it.
### Factory Dispatch
`BackendFactory::create` returns `Box<dyn FormBackend>`. The selection is a compile-time `#[cfg(feature)]` gate combined with runtime match (`backends/mod.rs:109`):
BackendType::Web { port } => Ok(Box::new(web::WebBackend::new(port))),
}
}
```
The backend code for a disabled feature is not compiled into the binary. The trait object provides runtime polymorphism; the feature gate provides compile-time dead-code elimination.
### Auto-Detection
`BackendFactory::auto_detect` follows a fallback chain (`backends/mod.rs:132`):
```text
TYPEDIALOG_BACKEND=tui → TUI (if feature active)
TYPEDIALOG_BACKEND=web → Web (port from TYPEDIALOG_PORT, default 9000)
default → Cli
```
### RenderContext
Passed to every render and field execution call:
```rust
pub struct RenderContext {
pub results: HashMap<String,Value>, // accumulated field values
pub locale: Option<String>, // locale override
}
```
`results` carries the accumulated answers from previous fields. `InquireBackend::execute_field_sync`
receives this as `previous_results` and uses it for `options_from` filtering in `Select` fields.
---
## Form Execution
### Three-Phase Execution
`execute_with_backend_two_phase_with_defaults` (`form_parser/executor.rs`) is the primary execution path: