/ home / stack / interface

The interface is a rental. The user experience is the residence.

Frameworks come and go on a 4-year cycle. The patterns underneath them — composition, state shape, render boundaries, accessibility — outlast every rewrite. We build interfaces against the patterns, then choose the framework that costs you the least to live with.

What an interface built our way looks like at the edge.

STREAMING · brillix.ai prod
Time to interactive
0.84s
↓ 73% vs framework default
Bundle delivered
42.0kb
gzip · route-split · cold
Lighthouse score
98/100
perf · a11y · seo · best
Cumulative layout shift
0.020
target < 0.10 · 5× under

We don't have favourites. We have verdicts.

Each row reflects what we'd actually pick for a new build today, scored against five axes that matter once an app reaches production. Updated quarterly. We've been wrong before; we'll be wrong again.

Framework
Maturity
Perf ceiling
Hire pool
Cost-to-leave
Verdict
React 19
USE
Next.js 15
USE
Svelte 5
USE
Astro
USE
SolidJS
WATCH
Angular 18
WATCH
jQuery
RESCUE

Use means we'd pick it for a new project today. Watch means we'd inherit it gracefully but not start there. Rescue means we extract you from it — we don't write more of it.

From DNS lookup to interactive — 840ms.

Real timing trace from a cold load of a Brillix.ai dashboard, captured in a Toronto edge POP. Every band below is a contract we negotiate with the browser, not a coincidence.

100ms 200ms 400ms 600ms 800ms DNS lookup 12ms TLS handshake 31ms Edge cache hit 7ms — Cloudflare worker HTML stream 40ms streamed CSS parse 18ms FCP first paint @ 280ms Critical fonts subset · 40ms · self-hosted Hero data fetch 63ms · streamed JSON LCP largest paint @ 480ms Hydration island-by-island · 100ms TTI interactive @ 840ms
Every band above is a budget we set, a config we own, and a number we log on every deploy.

The patterns we keep when the framework changes.

/ 01
Render boundaries are a budget, not a bug
Every component declares its render frequency, its data dependencies, and its hydration cost. We treat the boundary between server and client as a deliberate negotiation — never a default.
/ 02
State has a shape before it has a library
We model state as immutable transitions before we pick Zustand, Redux, signals, or context. The library is interchangeable; the shape is the product.
/ 03
Accessibility is the spec, not a sprint
WCAG 2.2 AA is the floor on day one. Keyboard, screen-reader, and motion-reduce paths ship with every component — there is no "we'll add it later" lane.
/ 04
The bundle is a public document
Every kilobyte that crosses the wire is justified in a build report your CFO could read. We delete more code than we add — and we measure both.

Six eras. One discipline.

2002 — 2008
Tables, then tableless
CSS finally allowed semantic HTML to mean something. We stopped abusing <table> for layout and started reasoning about the cascade. Box model wars. The first browser-engine fragmentation we'd actually have to live with.
HTML 4CSS 2jQuery 1.xPrototype
2009 — 2013
The MVC frontend moment
Backbone, Ember, Angular 1. The browser became an application runtime instead of a document viewer. We learned what state mutation costs you when it's invisible.
BackboneEmberAngular 1Knockout
2014 — 2018
Components, finally declarative
React shipped. Virtual DOM became a unit of accounting. We stopped describing how the UI changed and started describing what it should be. JSX as a portable contract.
React 0.14Vue 2WebpackBabel
2019 — 2022
The SSR reckoning
Single-page apps had become a tax on first paint. Next, Nuxt, Remix and SvelteKit dragged rendering back to the server — but smarter, streamed, and selectively hydrated.
Next.jsRemixSvelteKitAstro
2023 — 2025
Server components, signals, islands
RSC blurred the client/server line into a render graph. Signals returned as the answer to virtual DOM overhead. Islands of interactivity replaced page-level hydration.
RSCSolidSvelte 5 runesQwik
2026 — now
The compiler wins
React Compiler, Svelte's compiled reactivity, Solid's no-VDOM bet — frameworks finally vanish at build time. The interface ships as the smallest possible artifact that matches the source-of-truth contract.
React CompilerMillion.jsSolid 2Vite 6

A token-streaming UI that never blocks.

Brillix.ai needed a chat interface that could route between nine LLM providers without the user ever feeling a stall. The first token had to land before the human noticed they were waiting.

We built the interface as three concentric loops: an edge-rendered shell that paints in 280ms, an island-hydrated chat surface that listens before it's interactive, and a streaming token reducer that commits to the DOM at 120fps without ever triggering a layout pass.

The result is an interface where the perceived latency is the network — never the framework, never the bundle, never the renderer. When a provider stalls, we fall through to a warm replica and the user sees a tone shift, not a spinner.

"It's the only chat UI we've shipped where the engineers couldn't tell which provider was answering. That's the bar."

— Eng lead, Brillix.ai

Measured in production

FIRST_TOKEN120ms
TIME_TO_INTERACTIVE840ms
BUNDLE_DELIVERED42kb
TOKENS_RENDERED8.4B/mo
PROVIDERS_FRONTED9
FRAMEWORK_CHANGES0

Interface is one of four.

Have an interface that's fighting you?

Give us thirty minutes. We'll tell you whether it's the framework, the patterns, or the people — and what each fix actually costs.