Best Practices
Ansiq is not just a widget library. It has a real runtime core, and that means architectural mistakes tend to show up in a few very specific places:
- subtree replacement
- focus and input routing
- viewport / history
- continuity of interactive widget state
This page is therefore not about style. It is about engineering habits that keep a Ansiq app understandable as it grows.
1. Start from a small but real example
The best entry point is not a showcase like an activity monitor. It is something like:
- one
List - one selected item
- one footer
- a small amount of keyboard interaction
That is why the Guide uses list_navigation early.
If you start from:
- multiple panes
- realtime sampling
- remote loading
- several composed widgets
you will face too many problems at once, and you will not know whether a failure comes from:
- your domain model
- widget semantics
- or runtime boundaries
2. Use signals for facts, computed values for derivations, and effect for side effects
In Ansiq, a useful rule is:
signal: store factscomputed: store derived viewseffect: perform side effects
Do not use effect as a disguised second state container.
It is better suited to:
- starting or coordinating background work
- syncing with external systems
- logging
- non-UI side effects
If one value is just a function of another, prefer computed over maintaining a second mutable copy.
3. Keep application semantics separate from runtime behavior
Application semantics include:
- which process is selected
- which tab is active
- which OpenAPI operation is selected
- which transcript entries belong to the current turn
Runtime behavior includes:
- where focus currently is
- how cursor state survives subtree replacement
- how the viewport is reanchored
- when history is committed
If those become mixed, debugging gets much harder.
A simple smell test:
If business reducers or app state contain too many things like:
- continuity keys
- focus scopes
- invalidated regions
- reanchor plans
then runtime concerns are leaking upward.
4. Make continuity keys explicit, stable, and explainable
Ansiq already preserves several interaction states across subtree replacement:
- input cursor
- list/table selection
- tabs selection
- scroll offsets
But that only works reliably when you give stable identity to the places that actually need it.
Do not rely on “the sibling order happened to stay the same”.
Continuity keys are especially important for:
- reorderable sibling lists
- conditionally rendered panes
- regions where input or scroll position must survive replacement
5. Treat viewport and history semantics as product design
It is easy to think of the viewport as “just the area we draw into”.
But once an app has:
- multiple conversation turns
- committed history in scrollback
- a sticky footer or composer
- inline viewport reservation
viewport and history become product behavior.
You should decide deliberately:
- what belongs to the live viewport
- what should be committed to history
- what should reflow on resize and what should not
- whether user scroll-away-from-bottom changes automatic pinning behavior
These are not polish-stage concerns. They are architectural decisions.
6. Let narrative docs teach patterns, and API docs expose interfaces
A common mistake is to turn every page into an API catalog.
A healthier split is:
- Guide explains when and why to use a pattern
- Internals explains the system boundaries and tradeoffs
- API pages explain names, types, and entry points
That keeps the docs readable and reduces drift.
7. Prefer extracting composition widgets over repeating shell assembly
If you keep rebuilding patterns such as:
- header + status + summary
- transcript + footer
- detail pane + schema pane
extract a composition instead of hand-assembling it in every scenario.
This is the right home for things like:
SessionHeaderComposerBarBottomPaneSessionTranscript
8. Do not push everything into the runtime
Because Ansiq has a strong runtime core, there is a natural temptation to keep moving more and more logic into it.
That is the wrong direction.
The runtime should own:
- scheduling
- partial layout
- patch emission
- terminal session / viewport management
It should not own:
- business state modeling
- OpenAPI parsing
- system monitoring samplers
- app-level shell copy
9. When debugging, check the boundary before the widget
Many bugs look like rendering bugs but are really boundary bugs.
Examples:
-
a selected item disappears
maybe the widget is fine and the continuity key is missing -
a footer leaves visual residue
maybe the border renderer is fine and the real issue is viewport reanchor or full redraw semantics -
focus breaks after a pane reorder
maybe focus is fine and identity changed during subtree replacement
This is why Ansiq separates Guide and Internals. API lookup alone is not enough for this class of problems.
A short checklist worth remembering
If you only keep a few rules in mind, keep these:
- start from a small but real example
- use
signal/computed/effectfor clearly different jobs - keep app semantics separate from runtime behavior
- use continuity keys for nodes that need stable identity
- design viewport / history semantics deliberately
- extract composition widgets before copying shell assembly everywhere
- when debugging, inspect the boundary before you blame the widget