Skip to content

Getting Started

StateLoom is a universal state management SDK for JavaScript and TypeScript. It provides a signal-based reactive core with three paradigm adapters -- Store, Atom, and Proxy -- and framework adapters for React, Vue, Solid, Svelte, and Angular.

Why StateLoom?

  • One core, any paradigm: Choose the mental model that fits your team -- Zustand-like stores, Jotai-like atoms, or Valtio-like proxies. Switch or mix without rewriting your app.
  • Framework-agnostic: The reactive core runs anywhere JavaScript runs. Framework adapters are thin bridges, not heavy abstractions.
  • Composable middleware: Add persistence, devtools, tab sync, and undo/redo via a standard middleware interface.
  • Tiny core: @stateloom/core targets ~1.5 KB gzipped with zero platform dependencies.

Architecture at a Glance

Choose Your Paradigm

StateLoom offers three paradigm adapters. Each wraps the same signal-based core but provides a different API style:

StoreAtomProxy
Package@stateloom/store@stateloom/atom@stateloom/proxy
Mental modelSingle object with actionsComposable bottom-up atomsDirect mutation
Inspired byZustandJotaiValtio
Best forFeature-scoped state with actionsFine-grained, composable stateRapid prototyping, mutable-style
MiddlewareYesNoNo
TypeScriptInferred from initializerInferred from atom typeInferred from object shape

Not sure which to choose?

Start with Store. It covers most use cases, supports middleware (persistence, devtools, tab sync), and is the most familiar pattern for developers coming from Zustand or Redux. You can always add atoms or proxies alongside it later.

Installation

Install the core package plus your chosen paradigm and framework adapter:

bash
# Core + Store + React
pnpm add @stateloom/core @stateloom/store @stateloom/react
bash
# Core + Store + React
npm install @stateloom/core @stateloom/store @stateloom/react
bash
# Core + Store + React
yarn add @stateloom/core @stateloom/store @stateloom/react

Replace @stateloom/react with your framework adapter (@stateloom/vue, @stateloom/solid, @stateloom/svelte, or @stateloom/angular). You can also use the core directly without any framework adapter -- see Vanilla JS.

Quick Start: Signals (Core)

Signals are the fundamental reactive primitive. No paradigm adapter needed:

typescript
import { signal, computed, effect } from '@stateloom/core';

const count = signal(0);
const doubled = computed(() => count.get() * 2);

effect(() => {
  console.log(`Count: ${count.get()}, Doubled: ${doubled.get()}`);
  return undefined;
});

count.set(1); // logs: Count: 1, Doubled: 2
count.set(5); // logs: Count: 5, Doubled: 10

Quick Start: Store

Stores combine state and actions in a single object:

typescript
import { createStore } from '@stateloom/store';

const counterStore = createStore((set) => ({
  count: 0,
  increment: () => set((s) => ({ count: s.count + 1 })),
  decrement: () => set((s) => ({ count: s.count - 1 })),
  reset: () => set({ count: 0 }),
}));

counterStore.getState().increment();
console.log(counterStore.getState().count); // 1

Quick Start: Atom

Atoms are small, composable pieces of state:

typescript
import { atom, derived } from '@stateloom/atom';

const countAtom = atom(0);
const doubledAtom = derived((get) => get(countAtom) * 2);

Quick Start: Proxy

Proxies let you write state with regular mutations:

typescript
import { observable, observe } from '@stateloom/proxy';

const state = observable({ count: 0, name: 'Alice' });

observe(() => {
  console.log(`${state.name}: ${state.count}`);
});

state.count++; // logs: Alice: 1

Framework Guides

Choose your framework to see a complete integration guide:

FrameworkGuideExample App
Vanilla JS/TSVanilla JSexamples/vanilla-js/
React + ViteReact + Viteexamples/react-vite/
Next.js (SSR)Next.jsexamples/nextjs-ssr/
Vue 3Vueexamples/vue-vite/
SolidJSSolidJSexamples/solid-vite/
SvelteSvelteexamples/svelte-vite/
AngularAngularexamples/angular/
AstroAstroComing soon

Migrating from Other Libraries

StateLoom's paradigm adapters are designed to be familiar:

Coming fromUseKey differences
Zustand@stateloom/storeSame createStore(set => ...) API. Middleware uses an array instead of function wrapping.
Jotai@stateloom/atomSame atom() / derived() pattern. derived replaces Jotai's atom with a read function.
Valtio@stateloom/proxySame observable() / snapshot() API. observe() replaces subscribe().
Redux/RTK@stateloom/storeReplace slices with stores. No reducers needed -- use set() directly.
Pinia@stateloom/storeReplace defineStore with createStore. Actions are in the same object.

Next Steps