# Architecture

Source: /tuil/docs/concepts/architecture
Locale: en

Runtime ownership, package layers, lifecycle, and end-to-end control flow.



## System layers [#system-layers]

<Mermaid
  chart="flowchart TB
  subgraph Authoring[&#x22;Authoring and distribution&#x22;]
    CLI[&#x22;tuil CLI&#x22;]
    Registry[&#x22;component and skill registries&#x22;]
    Stories[&#x22;portable story catalog&#x22;]
  end
  subgraph Application[&#x22;Application boundary&#x22;]
    App[&#x22;TuilApp&#x22;]
    Lifecycle[&#x22;Lifecycle&#x22;]
    Services[&#x22;ServiceContainer&#x22;]
    Commands[&#x22;CommandRegistry&#x22;]
    Plugins[&#x22;PluginManager and extension registries&#x22;]
  end
  subgraph Interaction[&#x22;Interaction services&#x22;]
    Events[&#x22;EventBus&#x22;]
    Focus[&#x22;FocusManager&#x22;]
    Hotkeys[&#x22;HotkeyManager&#x22;]
    Router[&#x22;TerminalRouter&#x22;]
    Forms[&#x22;Forms&#x22;]
    Workflows[&#x22;Workflows and operations&#x22;]
    Themes[&#x22;ThemeController&#x22;]
  end
  subgraph Rendering[&#x22;Rendering and verification&#x22;]
    Renderer[&#x22;Renderer-neutral application&#x22;]
    Cell[&#x22;Bun-native cell backend&#x22;]
    Ink[&#x22;Ink adapter&#x22;]
    Components[&#x22;components and blocks&#x22;]
    Semantics[&#x22;SemanticRegistry&#x22;]
    Tests[&#x22;tests, docs, playground, showcase&#x22;]
  end
  CLI --> App
  Registry --> Components
  App --> Lifecycle
  App --> Services
  App --> Commands
  App --> Plugins
  App --> Events
  App --> Focus
  App --> Hotkeys
  Plugins --> Router
  Plugins --> Forms
  Plugins --> Workflows
  App --> Themes
  App --> Renderer
  Renderer --> Cell
  App --> Ink
  Ink --> Components
  Components --> Semantics
  Stories --> Tests
  Semantics --> Tests"
/>

The `TuilApp` instance is the ownership root. It constructs runtime services,
registers plugins, exposes typed extension registries, and disposes resources in
reverse ownership order.

## Application lifecycle [#application-lifecycle]

<Mermaid
  chart="stateDiagram-v2
  [*] --> configured
  configured --> initializing: initialize()
  initializing --> initialized: services + plugins ready
  initialized --> mounting: mount()
  mounting --> mounted: renderer attached
  mounted --> ready: ready()
  ready --> stopping: stop()
  stopping --> disposed: reverse teardown
  configured --> failed: reportError()
  initializing --> failed: reportError()
  mounting --> failed: reportError()
  ready --> failed: reportError()
  failed --> stopping
  disposed --> [*]"
/>

Every stage has a matching `app:*` event. Errors are reported through
`app:error`, then the configured error handler. Teardown is idempotent so error
paths and normal exit share the same ownership rules.

## Input flow [#input-flow]

<Mermaid
  chart="flowchart LR
  Bytes[&#x22;terminal bytes&#x22;] --> Ink[&#x22;Ink useInput&#x22;]
  Ink --> Overlay[&#x22;top overlay handler&#x22;]
  Overlay --> Layer[&#x22;scoped input layer&#x22;]
  Layer --> Hotkey[&#x22;hotkey manager&#x22;]
  Hotkey --> Focus[&#x22;default focus traversal&#x22;]
  Focus --> Component[&#x22;semantic component callback&#x22;]
  Component --> State[&#x22;runtime or application state&#x22;]
  State --> Render[&#x22;React rerender&#x22;]"
/>

The first consumer that handles input stops the chain. Active overlays suppress
application hotkeys, and input errors flow to `app.reportError()` instead of
escaping through an unobserved promise.

## Navigation flow [#navigation-flow]

<Mermaid
  chart="sequenceDiagram
  participant UI as Component
  participant Router as TerminalRouter
  participant Guard as Guards
  participant Loader as Loader
  participant Focus as FocusManager
  UI->>Router: navigate(target)
  Router->>Guard: before hooks
  Guard-->>Router: allow, redirect, or cancel
  Router->>Loader: load route data
  Loader-->>Router: result
  Router->>Router: commit history and layout
  Router->>Focus: restore route focus
  Router-->>UI: navigation complete event"
/>

## Ownership rules [#ownership-rules]

* `TuilApp` owns core services, plugins, event definitions, and extension
  registries.
* Providers own React subscriptions and unregister on unmount.
* Every runtime registration returns a disposer.
* Plugins deactivate and dispose in reverse dependency order.
* Workflow runners and operation executors own abort controllers and observers.
* Stories and tests always close render sessions, even after a failed action.

See [Events](./events), [Extensibility](./extensibility), and the
[package reference](/tuil/docs/reference/packages) for the concrete contracts.
