Web Native
“Web native” is a phrase that gets used loosely. In Kitsune it has a specific meaning:
Build with the browser’s primitives, not in spite of them.
Three commitments fall out of that.
1. Use real elements, not look-alikes
Section titled “1. Use real elements, not look-alikes”When the platform provides a primitive that does what you want, use it. When it doesn’t, wrap a native primitive in a custom element instead of replacing it with a <div>.
| You want | The platform gives you |
|---|---|
| A button | <button> |
| A modal | <dialog> |
| A tooltip / dropdown / menu | popover |
| An accordion | <details> / <summary> |
| A form input | <input>, <textarea>, <select> |
| A form-associated custom input | ElementInternals |
| A progress indicator | <progress> |
| A meter | <meter> |
Kitsune wraps these — never replaces them. <kit-button> puts a real <button> inside. <kit-dialog> puts a real <dialog> inside. The Quill tutorial uses native <details> for collapsible sections rather than building a custom one.
This isn’t a stylistic preference. The platform’s elements are the reason your app is accessible by default. Replace one and you take responsibility for everything it was doing.
2. The DOM is the context graph
Section titled “2. The DOM is the context graph”Every framework has its own concept of context — React Context, Vue provide/inject, Angular DI. Kitsune doesn’t add a parallel one. The DOM tree is the context graph.
<kit-shell name="quill"> <kit-boundary surface="workspace" feature="notes"> <kit-boundary surface="note-editor" entity-type="note" entity-id="42"> <kit-button meta-event="note.saved">Save</kit-button> </kit-boundary> </kit-boundary></kit-shell>When the button is clicked, the runtime walks up from the button through the DOM, collects the surrounding boundaries, and emits an event whose context is { surfaces: ['workspace', 'note-editor'], surface: 'note-editor', feature: 'notes', entity: { type: 'note', id: '42' } }.
You didn’t write a context provider. You wrote nested elements. The DOM tree carried the meaning.
This is the same pattern the platform uses for everything else. Forms are scoped by the nearest <form>. Labels are scoped by the nearest <label>. CSS scopes are scoped by the nearest layer or container. Kitsune extends this principle to product context.
3. Coordinate through events and commands
Section titled “3. Coordinate through events and commands”The browser already coordinates components through events. A submit event bubbles up; a submit listener on the form catches it. A click event bubbles up; whoever attached a delegated listener catches it.
Kitsune extends the same pattern to application-level meaning. An interaction emits a semantic event (note.saved) that bubbles up to the boundary, gets enriched, and reaches modules that observe it. A button asks for a command (dialog.open) that bubbles up to the boundary, gets dispatched, and is handled by a module.
There is no global event bus. There is no Redux store. There is no useContext. The runtime is plumbing for events you already think in terms of: something happened and please do this.
What you don’t have to learn
Section titled “What you don’t have to learn”Because Kitsune builds on platform primitives, the things you don’t have to learn are large:
- A virtual DOM model
- A reconciliation lifecycle
- A hook ordering rule
- A render-batching priority queue
- A server-component / client-component boundary system
- A custom routing convention
- A custom form library
- A CSS-in-JS runtime
The things you do learn:
- The DOM and its events (you already know these)
- Lit’s templating (one short page of docs)
- The Kitsune runtime loop (the next page)
- The metadata protocol (a one-page reference)
- A few Kitsune custom elements (kit-shell, kit-boundary, kit-button, kit-dialog, kit-toast-region, kit-field, kit-card)
That’s the surface area.
What you give up
Section titled “What you give up”Honesty: by going web-native you give up some opinionated convenience. There’s no kit dev server that scaffolds routes. There’s no opinionated state management. There’s no specific way to do data fetching — pick fetch, query libraries, server-sent events, whatever fits.
Kitsune is a coordination architecture, not a full-stack framework. For most teams, that’s the right scope. For some teams, it’s a gap.
If you’d like a full-stack framework that integrates the runtime, that’s a future package. The runtime is small and stable enough to build on.
Read more
Section titled “Read more”- The Runtime Loop — the next page
- The Problem — why this matters
- Custom Elements — the platform model Kitsune uses