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.
| Comparable to Rhai or Nushell | Integrates Nushell via `nu-plugin`/`nu-protocol` as an output channel |
### Differentiators
**Unified schema** — a single TOML file describes the same form for CLI, TUI, and HTTP. No per-backend code.
**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.
---
## BackendFactory
### The `FormBackend` Trait
All backends implement a single async trait (`backends/mod.rs:27`):
`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:
**Phase 1 — Selector fields first**
Fields that control `when:` conditionals are identified and executed before loading any fragments.
This ensures conditional branches are known before lazy-loading dependent content.
```rust
let selector_field_names = identify_selector_fields(&form);
// execute only selectors → populate results
```
**Phase 2 — Build element list with lazy loading**
With Phase 1 results known, fragments (`includes:`) are loaded only if their controlling condition is met.
```rust
let element_list = build_element_list(&form, base_dir, &results)?;
```
**Phase 3 — Execute remaining fields**
Iterates the element list, evaluates `when:` conditions per-element, and dispatches to the backend.
Two sub-modes:
-`DisplayMode::Complete` — passes all items and fields to `execute_form_complete` at once
(used by TUI and Web for reactive rendering)
- Field-by-field — sequential execution with condition evaluation per step (used by CLI)