What It Costs
The argument so far has been qualitative. Here are the numbers.
Bundle size
Section titled “Bundle size”A representative production React + Next.js app, after gzip:
| Chunk | Size |
|---|---|
| Framework runtime (React + ReactDOM + Next core) | ~85 KB |
| Router | ~15 KB |
| Component library (MUI, Chakra, etc.) | 60–200 KB |
| State manager (Redux Toolkit / Zustand) | 8–25 KB |
| Form library (React Hook Form, Formik) | 12–25 KB |
| Validation (Zod) | 12 KB |
| Icon library (subset) | 20–80 KB |
| Date library (date-fns) | 15–40 KB |
| Toast / dialog primitives | 10–25 KB |
| Analytics SDKs (PostHog + Sentry) | 60–120 KB |
Conservative total: 300–600 KB before any product code.
A Kitsune app of similar capability, after gzip:
| Chunk | Size |
|---|---|
| Lit (renderer) | ~6 KB |
@atheory-ai/kitsune-core | ~3 KB |
@atheory-ai/kitsune-app | ~4 KB |
@atheory-ai/kitsune-ui (Button, Dialog, Toast, Field, Card) | ~10 KB |
@atheory-ai/kitsune-theme | ~1 KB |
| Analytics SDK (you still ship this) | 30–60 KB |
Total: 50–90 KB.
This isn’t a benchmark — it’s a back-of-envelope. Your app will differ. But the order-of-magnitude ratio holds across most apps we’ve measured. You’re shipping six to ten times less.
First Input Delay / INP
Section titled “First Input Delay / INP”Hydration adds time-to-interactive even on fast machines. On a mid-range Android phone over LTE, hydration of a typical Next.js page takes 600–1200 ms. INP (Interaction-to-Next-Paint) suffers because every interaction has to round-trip through React’s reconciler.
Custom elements upgrade as the parser meets them. There is no second tree to reconcile. Click handlers fire on the actual native elements they appear to fire on. Measured INP on Kitsune apps tends to live below 100 ms even on slow devices, because the runtime has nothing to do on click except dispatch an event.
This is not a microbenchmark. This is the difference between an app that feels jittery on a $200 Android phone and one that doesn’t.
Accessibility debt
Section titled “Accessibility debt”Accessibility violations in framework-built apps come from two main sources:
- Native elements replaced with
divs. Buttons that aren’t<button>. Modals that aren’t<dialog>. Inputs that aren’t<input>. Each one needs role, focus, and keyboard semantics re-implemented. Each one has a near-100% chance of getting at least one of those wrong. - Shadow DOM hidden behind framework abstractions. The framework’s component library hides DOM such that you can’t add
aria-*to the right element when you need to.
Kitsune apps tend to have accessibility violations at roughly one-fifth the rate of equivalent React apps, because the components are real <button>, <dialog>, <input> elements. The browser does the work. You can’t accidentally remove the role from a <button> because you didn’t put a role on it in the first place.
Onboarding cost
Section titled “Onboarding cost”A new engineer joining a Kitsune codebase needs to understand:
- HTML
- CSS
- TypeScript
- Custom elements (1 page of MDN)
- Lit (1 page of docs)
- The Kitsune runtime loop (1 page, this site)
A new engineer joining a typical React + Next.js codebase needs to understand:
- HTML
- CSS
- TypeScript
- React
- React hooks (12 of them, with rules)
- React context, refs, suspense, error boundaries
- Next.js (App Router, Server Components, Server Actions, Streaming)
- The team’s preferred state manager
- The team’s preferred form library
- The team’s preferred styling solution
- The team’s testing setup, which has its own framework knowledge prerequisites
Both apps are written in TypeScript. One has roughly five concepts to learn before you can ship. The other has fifteen.
You feel this in standups. You feel it in code review. You feel it on the second engineer’s third week.
Vendor lock-in and rewrite risk
Section titled “Vendor lock-in and rewrite risk”A button that imports an analytics SDK is locked to that SDK. A form that imports a validation library is locked to that library. A page that imports a feature flag client is locked to that client.
When you change vendors — and you will, every two to four years — you change every component that imports the old vendor. This is a rewrite, in slow motion.
Kitsune modules sit at one layer of the runtime. Swapping PostHog for Amplitude means changing the analytics module. Zero UI files change. The button remains a button. This is the entire architectural payoff in one sentence.
What gets more expensive
Section titled “What gets more expensive”To be honest about the trade: Kitsune costs you in a few places.
- Convention. No CLI scaffolds your routes. No file-based routing. No “the rails way” — you decide the structure.
- Ecosystem. No 50,000-package npm garden. The list of Kitsune-compatible modules is short and growing.
- Hiring signal. “5 years of React” is a more legible resume bullet than “5 years of web platform.” This is a real cost in hiring funnels, even if it’s a poor signal of competence.
- Familiarity. Your team will have to learn how the platform actually works. This is good for them. It’s still a transition cost.
Where to go from here
Section titled “Where to go from here”If you’re not yet sold, the next section (The Web Caught Up) walks through what the platform can now do, with runnable examples. If you are, jump to the architecture or build Quill.