What if your application data, your DOM structure, your CSS, your routes, and your tests were all just... paths in the same store?
count -> application data
view.nodes.v0.tag -> the DOM structure
css.body.background -> a CSS property
route.current -> the current URL
tests.passed -> live contract results
All readable with store.get(path). All writable with store.set(path, value). All reactive with store.subscribe(path, fn).
Three methods. One mental model. That's EveryState.
Quick note before we dive in: You can use any frontend library or framework as the rendering/view layer. Combine it with
@everystate/view, or use it exclusively. Want React for rendering and the EveryState ecosystem for state, CSS, routing, and testing? That works.@everystate/reactprovidesusePathanduseIntenthooks so React components can subscribe to the store. EveryState doesn't replace your view layer - it gives everything around it a unified address space.
What does it look like?
Here's a complete counter app:
import { createEveryState } from '@everystate/core';
import { createApp } from '@everystate/view/app';
import { createStyleEngine } from '@everystate/css';
import { increment } from './increment.js';
import { decrement } from './decrement.js';
const store = createEveryState({ count: 0 });
createStyleEngine(store);
const { cleanup } = createApp(store, '#app',
{
tag: 'div', class: 'counter', css: { textAlign: 'center' },
children: [
{
tag: 'h1', text: 'Count: {count}'
},
{
tag: 'button', text: '-', onClick: 'decrement'
},
{
tag: 'span', text: '{count}', class: 'value',
css: { fontSize: '3rem', fontWeight: '700' }
},
{ tag: 'button', text: '+', onClick: 'increment' },
]
},
{ increment, decrement }
);
// increment.js
export function increment(store) {
store.set('count', store.get('count') + 1);
}
That's it. No JSX. No build step. No bundler. Open the HTML file, and it runs.
The CSS? It's co-located right on the view nodes. createApp auto-extracts css: {} to css.{class}.{prop} paths in the store, and the style engine reactively applies them to the DOM via CSSOM.
The handlers? store is auto-injected as the first argument. Write a function, pass it by name. No manual wiring.
The Ecosystem
| Package | What it does | External deps |
|---|---|---|
@everystate/core |
The store. get, set, subscribe, wildcards, async. |
Zero |
@everystate/view |
View-as-state. Normalize, flatten, project. createApp. |
Zero |
@everystate/css |
Reactive CSSOM. Design tokens, typed CSS. | Zero |
@everystate/renderer |
Direct-binding renderer. bind-*, set, each attributes. |
Zero |
@everystate/router |
SPA routing as state. Routes are just store paths. | Zero |
@everystate/perf |
Performance monitoring overlay. | Zero |
@everystate/test |
Event-sequence testing. createEventTest. |
Zero |
@everystate/react |
React adapter. usePath, useIntent. |
Zero (react is peer) |
Total external dependencies across the entire ecosystem: zero. Every package is a native ES module. No bundler. No transpiler.
The Core Idea: Dot-Path Addressable Everything
The dot-path is the central concept. It's a universal address for everything in the application - like a file path in Unix or a URL on the web.
store.get('css.body.background') // read a CSS value
store.set('css.body.background', '#000') // change it reactively
store.subscribe('css.*', fn) // watch all CSS changes
store.subscribe('*', fn) // watch everything
In most frameworks, your data lives in one system (useState, ref, signals), your styles live in another (CSS files, Tailwind, styled-components), your routes in another (react-router, vue-router), your tests in another (Jest, Vitest). Each has its own API, its own mental model, its own debugging tools.
In EveryState, every concern uses the same three methods. When you learn how @everystate/core works, you already know how @everystate/css, @everystate/router, and @everystate/test work - they all just read and write paths in the same store.
How Does It Compare?
I've been building EveryState as an alternative to the frameworks I've been using (and teaching) for years. Here's an honest comparison across the landscape. I'll highlight what each tool does well and where EveryState offers a different trade-off.
vs React
| Dimension | React | EveryState |
|---|---|---|
| Rendering | Virtual DOM diffing, component re-renders | Surgical O(1) updates via path subscriptions |
| State |
useState, useReducer, useContext, plus external libs |
One store, dot-paths |
| Build step | Required (JSX compilation) | None (native ES modules) |
| CSS | Many options: CSS Modules, styled-components, Tailwind |
css.{selector}.{prop} in the store, reactive |
| Testing | Jest + RTL + act() + mock providers |
createEventTest - assert on state, no DOM needed |
| Bundle | ~45KB gz (react + react-dom), plus tooling | ~4KB gz (core only) |
React's component model is built on running functions and diffing their output. This is powerful and well-understood, but it creates a class of optimization work (React.memo, useMemo, useCallback, dependency arrays) that EveryState sidesteps entirely - subscriptions only fire for the exact path that changed.
React's strengths: Massive ecosystem, huge hiring pool, battle-tested at enormous scale (Meta, Netflix, Airbnb), mature SSR via Next.js, React Native for mobile. React is the industry standard for good reason.
EveryState's different trade-off: No re-renders to optimize. No hook rules to remember. No build step. The entire update model is "path changed -> subscriber fires." That's it.
vs Vue
| Dimension | Vue | EveryState |
|---|---|---|
| Reactivity | Proxy-based, component-scoped | Path-based subscriptions, global store |
| Templates |
.vue SFCs with v-if, v-for, v-bind
|
Plain JS objects |
| Build step | Practically required for .vue files |
None |
| State sharing |
provide/inject, Pinia |
One store - everything shared by default |
Vue's Composition API and EveryState are aiming at the same target: fine-grained reactivity. Vue layers it on top of a component model and template compiler. EveryState starts from the store and derives everything else from it.
Vue's strengths: Excellent documentation, approachable learning curve, Vite (born in Vue-land), growing enterprise adoption, well-designed ecosystem (Pinia, Vue Router).
vs Angular
| Dimension | Angular | EveryState |
|---|---|---|
| Architecture | Modules, components, services, DI, decorators, RxJS | Store + view spec + handlers |
| Build step | Mandatory (CLI, TypeScript, zone.js) | None |
| Bundle | ~65KB+ gz minimum | ~4KB core |
Angular is a comprehensive, opinionated platform. It brings a lot of structure out of the box - which is valuable for large teams that need strong conventions. Its recent adoption of signals (Angular 17+) moves it toward the same fine-grained reactivity model that EveryState uses.
Angular's strengths: Enterprise adoption, strong conventions reduce decision fatigue, Google backing, TypeScript-first, comprehensive CLI tooling.
EveryState's different trade-off: Minimal API surface (get, set, subscribe) instead of a large framework vocabulary. Convention over configuration, but the conventions are just path naming.
vs Svelte
| Dimension | Svelte | EveryState |
|---|---|---|
| Approach | Compiler turns .svelte into optimized vanilla JS |
Already vanilla JS - no compiler needed |
| Build step | Required (Svelte compiler) | None |
| Runtime size | Near-zero (compiled away) | ~4KB (nothing to compile) |
Svelte is the closest in philosophy to EveryState. Both care deeply about small output and developer experience. Both reject the virtual DOM. The key difference is the mechanism: Svelte achieves its goals through a compiler that transforms custom syntax into optimized JS. EveryState achieves them through a simpler architecture where the code you write is the code that runs.
Svelte 5's runes ($state, $derived, $effect) work inside .svelte files. EveryState's reactivity works in any .js file, in the browser console, in Node.js - anywhere JavaScript runs.
Svelte's strengths: SvelteKit is a mature full-stack framework. Compiled output is highly optimized. Template syntax feels natural to HTML developers. Growing community and adoption.
vs Solid
Solid is architecturally the most similar to EveryState in the mainstream landscape. Both use fine-grained reactivity, both skip the virtual DOM, both achieve O(1) updates.
The key difference is the address model. Solid's signals are reactive values, but they don't have addresses - you need a reference to a specific signal to read it. EveryState's dot-paths ARE addresses. Any part of the system can access any other part just by knowing the path string. This is what enables cross-cutting features like store.subscribe('*', fn) for activity logging, or tests that assert on CSS paths.
Solid's strengths: SolidStart for SSR, JSX familiarity for React developers, excellent performance benchmarks, growing community with corporate backing.
vs Elm
Elm pioneered the unidirectional data flow (Model-Update-View) that inspired Redux and much of the React ecosystem. EveryState's architecture shares that same DNA. The difference: Elm requires learning a custom ML-family language, while EveryState is plain JavaScript.
Elm's "no runtime exceptions" guarantee is genuinely impressive. EveryState takes a different approach with runtime contracts via @everystate/test - live assertions that run continuously and report violations in real-time, inside the same store.
vs jQuery
jQuery and EveryState share a quality that's easy to overlook: no build step, direct platform access. Drop a script tag and go.
The difference: jQuery is imperative DOM manipulation (the DOM is the source of truth). EveryState is declarative state projection (the store is the source of truth, the DOM is a projection of it). You get jQuery's low-friction setup without the maintenance challenges of imperative DOM code at scale.
vs Preact
Preact proves that React's ~45KB isn't necessary for the same API. But Preact deliberately inherits React's architectural decisions: virtual DOM, component re-renders, hook rules. It's a lighter React. EveryState isn't trying to be a lighter anything - it's a different approach to the same problem.
vs State Management Libraries
This is where the comparison gets most interesting, because @everystate/core IS a state management library - but it's also the foundation for everything else in the ecosystem.
vs Redux
| Dimension | Redux | EveryState |
|---|---|---|
| Mutations | Action objects with type strings |
store.set('path', value) - the path is the action type |
| State updates | Reducer functions return new state |
set writes directly |
| Boilerplate | Types, creators, reducers, selectors, slices | store.set('count', 1) |
| DevTools | Time-travel, action log, state diff |
subscribe('*', fn) + perf overlay |
Redux got the big idea right: single source of truth with predictable state flow. EveryState keeps that insight and strips the ceremony. The dot-path IS the action type. set IS the reducer. get IS the selector.
Redux's time-travel DevTools are a genuinely great feature. EveryState has snapshot()/restore() on the roadmap for similar capability.
vs Zustand, Jotai, Valtio, Pinia, MobX
Zustand is excellent - probably the best React state library. But it's React-bound:
useStoreis a hook, subscriptions trigger component re-renders. EveryState's store feeds everything: view, CSS, routes, tests.Jotai takes a bottom-up atomic approach, similar in concept to paths. The key difference: Jotai atoms are scattered across files with no central registry. EveryState paths form a single enumerable tree.
Valtio uses Proxies for transparent reactivity (
state.count++just works). EveryState requires explicitstore.set()calls - one more line, but every mutation is visible and greppable in the codebase.Pinia is well-designed for Vue. EveryState is framework-agnostic - it works with Vue, React (via
@everystate/react), or vanilla JS.MobX tracks dependencies automatically, which is powerful but creates dependency graphs that can be hard to debug. EveryState's subscriptions are explicit - the debugging surface is flat.
vs XState
XState and EveryState solve different problems. XState models processes (state machines with transitions and guards). EveryState models data (values at paths). They're complementary. You could use XState to manage complex flows and write results to an EveryState store.
vs Meta-Frameworks (Next.js, Nuxt, Remix)
EveryState does not have a meta-framework equivalent. No "EveryState-Next." This is the biggest ecosystem gap.
| Feature | Meta-frameworks | EveryState |
|---|---|---|
| Routing | File-based routing |
@everystate/router - routes are store paths |
| SSR | Server components, streaming |
serialize(resolveTree(...)) produces HTML. No server pipeline yet. |
| Deployment | Platform-specific (Vercel, Cloudflare) | Any static file server |
For SPAs - dashboards, admin panels, internal tools, creative tools, editors - SSR is often unnecessary, and EveryState's zero-build deployment to any CDN is a genuine advantage. For SEO-critical marketing sites, the meta-frameworks are the right choice today.
Honorable mentions
- HTMX - Server-driven (hypermedia) vs EveryState's client-driven (state). Different philosophies, complementary use cases.
-
Alpine.js - Sprinkle reactivity into HTML. Similar spirit to
@everystate/renderer. Alpine scopes state to DOM elements; EveryState centralizes it. -
Astro - Content-first with islands of interactivity. Each island could be a
createAppcall - a natural fit worth exploring. - Qwik - "Resumability" requires serializable state. EveryState's state is already fully serializable, making a similar strategy architecturally possible.
- Tailwind - Utility classes in HTML vs utility properties in the store. Both avoid writing CSS files. EveryState's approach is reactive (change a value, style updates); Tailwind's is static.
Ease of Use
| Framework | "Hello World" | Files needed | Build step |
|---|---|---|---|
| React (Vite) | ~10 lines | ~12 generated | Yes |
| Angular | ~20 lines | ~20 generated | Yes |
| Svelte | ~5 lines | ~8 generated | Yes |
| EveryState | ~10 lines | 2 (HTML + JS) | No |
The initial setup is comparable. Where EveryState differs is how complexity scales. In most frameworks, growing the app means adding new libraries for state, CSS, routing, testing - each with its own API and learning curve. In EveryState, you add more paths to the same store. The API stays get, set, subscribe. The mental model stays flat.
Learning Curve
To be productive in React, you typically need to understand: JSX, components, props, hooks (useState, useEffect, useRef, useCallback, useMemo, useContext), hook rules, effect cleanup, dependency arrays, React.memo, Context API, a state management library, a CSS solution, a router, a testing library, build tool configuration. That's roughly 15+ concepts before you're comfortable.
To be productive in EveryState:
-
createEveryState(initialState)- create a store -
store.get('path')- read a value -
store.set('path', value)- write a value -
store.subscribe('path', fn)- react to changes - Wildcards:
store.subscribe('path.*', fn) - View specs: objects with
tag,text,class,children,css,onClick -
createApp(store, el, viewSpec, handlers)- mount an app - Handlers receive
storeas their first argument
8 concepts. And when you add CSS, routing, or testing capabilities, you don't learn new APIs - they all use the same get/set/subscribe on the same store.
Developer Experience
Here's what daily development looks like with EveryState v1.1.0:
Define a view node - structure, content, behavior, and style in one place:
{ tag: 'button', class: 'btn', text: 'Click me', onClick: 'handleClick',
css: { padding: '8px 16px', borderRadius: '4px', cursor: 'pointer' } }
Write a handler - a plain function, testable in isolation:
export function handleClick(store, event) {
store.set('clicked', true);
}
Test it - no DOM, no browser, no mocking:
const t = createEventTest({ clicked: false });
t.trigger('clicked', true);
t.assertPath('clicked', true);
Derive reactive values - plain JavaScript:
store.subscribe('count', () => {
const count = store.get('count');
store.set('css.value.color', count > 0 ? 'green' : count < 0 ? 'red' : 'gray');
});
What's still on the roadmap
- IDE integration - No autocomplete for dot-paths yet. Path strings don't give the editor type information the way typed props do. This is the biggest DX gap.
- Browser DevTools - React DevTools and Vue DevTools are mature. EveryState has a performance overlay, but not a full state tree inspector extension. Coming.
- Hot Module Replacement - Currently save-and-refresh. Live reload is planned.
Scalability and Maintainability
store.get('path') is O(1). store.set('path', value) is O(1) plus the cost of notifying subscribers for that specific path. Paths provide natural namespacing:
user.profile.name
products.list.0.name
cart.items.0.productId
view.nodes.v42.text
css.card.borderRadius
route.current
The path naming convention IS the architecture. No "modules," no "slices" - just paths with conventional prefixes.
For maintainability, the difference is in dependency surface. A typical React project maintains: application code + the dependency tree + the build pipeline + TypeScript config + linting config for JSX. In EveryState, you maintain: application code + @everystate/core (which has zero transitive dependencies). The surface area for "something broke because a dependency updated" is dramatically smaller.
Does it scale to large teams? This is an honest open question. EveryState's simplicity means fewer concepts to miscommunicate. But it also means teams need their own conventions for path organization. Frameworks with more structure (Angular, for instance) enforce those conventions for you. EveryState trusts developers to define their own.
The 5-Year Question
This is where I think EveryState makes its strongest case.
A brief history of frontend "best practices"
| Year | The recommendation | Status in 2026 |
|---|---|---|
| 2014 | Angular 1 + Grunt + Bower | Dead. Complete rewrite (Angular 2+ is a different framework). |
| 2016 | React + Create React App | CRA abandoned. Meta recommends Next.js. |
| 2017 | Vue 2 + Vuex + Vue CLI | Vue 2 EOL. Vuex replaced by Pinia. Vue CLI replaced by Vite. |
| 2018 | React + Redux + styled-components | Redux declining. styled-components declining. |
| 2021 | Svelte 4 + SvelteKit | Svelte 5 rewrote the reactivity model. |
| 2023 | Next.js App Router + React Server Components | Significant community pushback. API still evolving. |
The pattern is clear: frameworks churn, build tools churn, state libraries churn. The things that DON'T churn are web platform APIs: document.createElement, element.addEventListener, fetch, ES modules, CSS properties. These have been stable for years, some for decades.
What EveryState is built on
- ES modules - Part of the JavaScript language spec since 2015. Supported in all browsers.
-
DOM APIs -
createElement,textContent,addEventListener- stable since the 2000s. -
CSSOM -
CSSStyleSheet.insertRule- standardized, stable. -
Plain objects and strings -
{ tag: 'div', text: 'hello' }. No custom syntax. - Import maps - Browser-native module resolution. No bundler needed.
- Zero dependencies - Nothing external can break.
An EveryState app written today will run in any browser that supports ES modules - that's every modern browser, and has been since 2018. There is nothing to update, nothing to migrate, nothing that can be deprecated out from under you.
Compare that to a React app written in 2021: Create React App is abandoned, Webpack config may need updating, React 17 to 18 to 19 involves migration work, class components to hooks is an ongoing refactor, Redux to Zustand is a rewrite, styled-components to Tailwind is a rewrite.
EveryState aims for code that you write once and that keeps running.
Five Principles
These are the design principles behind every decision in the EveryState ecosystem:
1. Total Backwards Compatibility
Once the API stabilizes: open-closed principle. get, set, subscribe are the foundation and they're not changing. New capabilities come as additions (snapshot(), derived(), new packages), not as modifications to existing APIs. The goal is a plugins-only architecture from that point forward.
2. As Close to the Platform as Possible
EveryState uses: ES modules, DOM APIs, CSSOM, plain JavaScript, import maps.
It does not use: Webpack, TypeScript, JSX, Babel, PostCSS. No configuration files. No node_modules with hundreds of megabytes of transitive dependencies. Save a file, refresh the browser. That's the dev loop.
3. No Magic
Every operation is explicit and traceable:
-
store.set('count', 5)- the value atcountbecomes5. Nothing else happens. -
store.subscribe('count', fn)-fnis called whencountchanges. Nothing else. -
onClick: 'increment'- the handler namedincrementis called on click. Nothing else.
No Proxy traps, no compiler transforms, no automatic dependency tracking, no monkey-patching of browser APIs. The source of @everystate/core is ~300 lines of readable JavaScript.
4. As Simple as Possible, but Not Simpler
EveryState includes wildcards, setMany, queryClient, forEach, and classIf because real applications need them. It does not include a virtual DOM, lifecycle hooks, dependency injection, or a template language because this architecture doesn't need them.
5. Dot-Paths Are a Superpower
store.subscribe('*', fn); // complete activity log of the entire app
store.set('css.card.borderRadius', '8px'); // CSS is just state
store.subscribe('count', () => { // live runtime contracts
store.set('tests.countIsNumber', typeof store.get('count') === 'number');
});
The dot-path turns the entire application into an addressable, observable, serializable structure. Data, view, CSS, routes, tests - all in one place, all with the same API.
Current Limitations
Every tool has trade-offs. Here's where EveryState is today:
-
No SSR pipeline - The building blocks exist (
serializeproduces HTML from state), but there's no server-side rendering framework, hydration strategy, or streaming. For SEO-heavy sites, use a meta-framework. -
No TypeScript - By design. Dot-paths are strings; the IDE doesn't know what's at
'user.profile.name'. Runtime contracts via@everystate/testprovide safety at a different layer. - Young ecosystem - No component marketplace, no DataGrid, no DatePicker. You build with primitives or integrate vanilla JS libraries.
- Early-stage adoption - React has Meta, Netflix, Airbnb. EveryState has a growing collection of examples and a thorough test suite. It's proving itself, but it's early.
- DevTools in progress - Performance overlay exists. A full browser extension with state tree inspection is on the roadmap.
Try It
Option A: npm (recommended)
mkdir my-app && cd my-app
npm init -y
npm install @everystate/core
Create two files:
index.html
<!DOCTYPE html>
<html>
<head><title>EveryState</title></head>
<body>
<h1 id="display">0</h1>
<button id="inc">+</button>
<button id="dec">-</button>
<script type="importmap">
{
"imports": {
"@everystate/core": "./node_modules/@everystate/core/index.js",
"@everystate/core/everyState.js": "./node_modules/@everystate/core/everyState.js",
"@everystate/core/queryClient.js": "./node_modules/@everystate/core/queryClient.js"
}
}
</script>
<script type="module" src="app.js"></script>
</body>
</html>
app.js
import { createEveryState } from '@everystate/core';
const store = createEveryState({ count: 0 });
store.subscribe('count', () => {
document.getElementById('display').textContent = store.get('count');
});
document.getElementById('inc').addEventListener('click', () => {
store.set('count', store.get('count') + 1);
});
document.getElementById('dec').addEventListener('click', () => {
store.set('count', store.get('count') - 1);
});
Serve it with any static file server (npx serve ., python3 -m http.server, VS Code Live Server - anything). Open the page. That's a running EveryState app. No build step, no bundler, no config files.
Option B: CDN (zero install)
If you want to skip npm entirely, esm.sh bundles the package into a single browser-ready module:
<script type="importmap">
{
"imports": {
"@everystate/core": "https://esm.sh/@everystate/core@1.0.6"
}
}
</script>
<script type="module" src="app.js"></script>
Same app.js as above. No npm, no node_modules. Just an HTML file, a JS file, and a CDN URL.
What's next after the counter?
- Add
@everystate/viewfor declarative view specs andcreateApp - Add
@everystate/cssfor reactive styling viacss.*paths - Add
@everystate/routerfor SPA routing as state - Add
@everystate/testfor live runtime contracts
Each package uses the same store, the same get/set/subscribe. No new mental models.
Current versions: @everystate/core 1.0.6 | @everystate/view 1.1.0 | @everystate/css 1.0.10
If you found this interesting, check out the npm package or star the repo. I'd love to hear what you think in the comments - what would you build with addressable state?
Top comments (0)