Docs Philosophy
What we do not do
An architecture is explained by what it leaves out. Each omission below is a rule in the repository's architecture contract, with the reason and the place it is enforced.
On this page
No JavaScript dialog
We do not build a JavaScript dialog when <dialog> is sufficient. The browser
provides the modal top layer, page inertness, Escape, focus return and the backdrop; an
open-state controller, a focus trap and a portal would duplicate them and add a dependence on
hydration. Enforced by the dialog contract's "What the package does not do" section and by the
native-only fixture, whose production build emits a Svelte Lean chunk of 0 B.
No listener per instance
We do not create one event listener per primitive instance by default. A Tier 1 behavior
installs one listener per event type on the document runtime and routes along composedPath(); a thousand tabs roots keep one click and one keydown. Enforced by the forbidden changes, by tabs.test.ts and by the release
gate in listeners.spec.ts,
which counts listeners two independent ways for 1 and 1000 roots.
No MutationObserver discovery
We do not use a generic MutationObserver to discover primitives or run their
lifecycle. A root inserted later is found by the router on its first event, so the observer
would only add work on every unrelated DOM update and eager controllers for untouched instances.
Enforced by ADR 0004, by tests that
mount roots after registration, and by the audit command grep -rn MutationObserver packages/*/src, which returns nothing (audit).
No mirrored native state
We do not mirror native browser state into Svelte state or stores without a reason. open, checked, disabled and focus already exist in the
DOM; a copy creates synchronization work and a second value that can be wrong. Tabs keep their
selection in aria-selected, tabindex and hidden, and the
behavior source contains no WeakMap, which its unit test asserts. The table's state
object is application state by design, not a mirror.
No Provider
We do not require a Provider because other libraries have one. Theme lives in CSS tokens on the
root; the runtime attaches to the document; there is no context to wrap the application in and
no .svelte file in the runtime packages. Enforced by the forbidden changes and the
audit command grep -rni provider packages/*/src, which returns nothing.
No positioning engine
We do not ship a positioning engine when CSS anchor positioning and the invoker's implicit
anchor solve the case. Popovers are placed by position-area in the stylesheet;
where the browser lacks it, the popover keeps the platform's default placement, and that
fallback is documented rather than hidden. No package has a positioning dependency (grep -rni floating-ui packages/*/src returns nothing).
No forced virtualization
We do not force virtualization onto small tables, and we do not turn every cell into a
persistent component. <DataTable /> renders a native <table>; virtual rows are a future, optional entry point and are not shipped
today. Supporting a feature does not mean shipping it: grouping, pivot, clipboard, export,
server data and persisted state stay out of the bundle until imported, which the table-basic
fixture asserts.
No hidden runtime cost
We do not hide runtime cost. Every primitive page carries a runtime block with its tier, its shared listeners and its measured behavior JavaScript, read from the contract and the size file; the tabs registration including the shared kernel is 1521 B brotli. The proof page reads the listeners of the page you are on, and every number on the site comes from a committed measurement file or reads "not measured".
Also not
- No random ids for ARIA relationships; ids are authored, so server output is correct.
- No
documentorwindowaccess at module evaluation; every entry imports under Node. - No
eval, nonew Function, no string-to-code attributes; a strict Content Security Policy has nothing to object to in the packages. - No Tailwind or CSS-in-JS dependency in any package.
- No production dependency without a written reason why the platform is insufficient.
- No root entry that registers every behavior; registration is a subpath and a side effect.
- No rename of a protocol attribute, event, token or export without a deprecation window.
The full list, with the reasons, is the "Forbidden changes" section of AGENTS.md; the costs of these choices are on Trade-offs.