# Architecture
**Workspace members:**
| `quadraui/` | Core library: primitives, types, theme, backend traits, TUI, GTK, macOS, and Windows rasterisers. |
| `kubeui-core/` | Domain logic for a Kubernetes dashboard demo. No rendering deps — testable in isolation. |
| `kubeui/` | TUI Kubernetes dashboard. Real consumer of every TUI rasteriser. |
| `kubeui-gtk/` | GTK Kubernetes dashboard. Same domain logic as `kubeui`. |
**Two-layer split** inside `quadraui/`:
- `quadraui/src/primitives/` — backend-agnostic widget descriptions +
layout functions + hit_test. **Must NOT depend on `ratatui`, `gtk4`,
`cairo`, or any backend crate.** Tests live as inline `#[cfg(test)]
mod tests` blocks at the bottom of each primitive file.
- `quadraui/src/tui/`, `quadraui/src/gtk/`, `quadraui/src/macos/`, and
`quadraui/src/win/` — the four backend rasterisers (`tui`, `gtk`,
`macos`, `win` feature-gated respectively). Each consumes the
primitive's `layout()` and paints verbatim. **Must NOT contain layout
decisions** that the primitive could express. See the root
`README.md`'s *Status* section for how far each backend actually
gets today.
**Compose helpers** in `quadraui/src/compose/` sit above primitives
and below apps. They own interaction state machines for common
multi-primitive compositions so consumers don't reimplement them:
- `FocusRing` — Tab/Shift+Tab cycling through widget IDs.
- `MenuSystem` — MenuBar + ContextMenu dropdown interaction.
- `SidebarSystem` — MSV + TreeView sidebar panel interaction.
**GTK hosting helpers** in `quadraui/src/gtk/`:
- `MenuOverlay` — encapsulates the DrawingArea boilerplate for
MenuSystem dropdown popups when the menu bar lives in a separate
titlebar widget. Handles the negative-y coordinate transform,
`set_focusable(false)`, `can_target` toggling, surface clearing,
and draw/click/motion wiring. Apps that use the single-DA runner
don't need this — the dropdown paints on the same surface.
**Cross-backend runtime plumbing** sits at the top of `quadraui/src/`,
alongside `backend.rs` and `frame.rs`, shared by all four backends
instead of duplicated per-runner:
- `runtime.rs` — shared plumbing for the per-backend runners (`tui::run`,
`gtk::run`, `macos::run`, `win::run`): the post-event `EventOutcome`
enum and "apply this outcome to the live window", previously
duplicated (or silently missing) across the four runners (#496/#813).
- `dispatch.rs` — cross-backend mouse + scroll dispatch. Backends call
free functions (`dispatch_mouse_down`, `dispatch_mouse_drag`,
`dispatch_mouse_up`, `dispatch_scroll`, `dispatch_click`) with raw,
platform-translated events; a shared [`ModalStack`] decides whether an
open modal — never a base-layer widget behind it — receives the event
(issue #192).
- `shell.rs` — the `ShellApp` trait + `ShellConfig` for apps that want a
full `AppShell` (activity bar + sidebar + main content) instead of
implementing `AppLogic` directly. Each backend's `run_with_shell()`
owns window creation, event wiring, and chrome rendering; the
consumer renders only its own content. `shell_adapter.rs` is the
shared `AppLogic` impl every backend's shell runner instantiates to
avoid re-deriving that routing per backend.
- `paint_surface.rs` — `PaintSurface`, the low-level drawing-verb trait
underneath the three pixel backends (GTK, macOS, Windows), factoring the
"how the platform draws at all" half of `Backend` (frame lifecycle,
measurement, fill/stroke/text primitives) out from the "what to
paint" half — one `draw_*`/`*_layout` method per primitive (issue
#807; `pub` since issue #1101, reached via `Backend::paint_surface`).
**Backend trait** in `quadraui/src/backend.rs` plumbs frame state, the
`set_theme` / `set_nerd_fonts` setters hosts call once per frame, *and*
one `draw_*` method per primitive (`docs/decisions/BACKEND_TRAIT_PROPOSAL.md` §4,
Decision 2 = B) — adding a primitive is a breaking change to the trait,
intentionally. Each backend's `draw_*` method is a thin wrapper around
that backend module's own internal `pub fn draw_*` free function (e.g.
`impl Backend for WinBackend { fn draw_tree(...) {
quadraui_win::draw_tree(...) } }`); the trait itself has no free-standing
"cross-cutting state" carve-out.
**`set_cell` / `cairo_rgb` / `ratatui_color` / etc.** are private
backend helpers — never call them from primitives.
**Frame composition** in `quadraui/src/frame.rs` sits above `Backend`:
`ScreenLayout` + `Surface` is the canonical way for a consumer to
assemble a top-level screen from multiple primitives — pushing
`Surface` entries and calling `ScreenLayout::draw` routes every backend
through one call site (rather than each backend calling
`Backend::draw_<name>` at its own, potentially divergent, call site)
and derives the click hit-map from the same data that was painted.
`Backend::draw_*` methods remain the public, low-level rasteriser entry
point underneath — `ScreenLayout::draw` calls them internally, and
they're the only path for primitives that don't have a `Surface`
variant yet. See `docs/decisions/DECISIONS.md` D-006 and
`docs/PRIMITIVE_RULES.md` "One primitive, one canonical paint path"
(issue #456).
**Audits.** `docs/audits/FRAMEWORK_AUDIT_2026-09-26.md` is the most recent
independent review of quadraui as an app framework: its verdict, the
measured numbers, and the severity-ranked roadmap behind epics #1095
(widget model) and #1096 (language bindings). The living, release-ordered
version of that roadmap is [`ROADMAP.md`](../../ROADMAP.md) at the repo root. `docs/SMELL_AUDIT_2026-07.md`
is the earlier code-smell audit.