This file configures Claude for working on the @stateloom/* monorepo.
StateLoom is a universal state management SDK published under the @stateloom/* npm scope. It provides a signal-based reactive core with paradigm adapters (store, atom, proxy), framework adapters (React, Vue, Solid, Svelte, Angular), and composable middleware (devtools, persist, sync, history).
| Layer | Packages | Responsibility |
|---|---|---|
| 1. Reactive Core | @stateloom/core |
Signal-based push-pull hybrid reactivity: signal, computed, effect, batch, Scope. ~1.5 KB gzipped, zero platform APIs. |
| 2. Paradigms | store, atom, proxy |
Translate familiar API patterns (Zustand, Jotai, Valtio) into operations on core signals. Independent siblings — never import each other. |
| 3. Framework Adapters | react, vue, solid, svelte, angular |
Thin bridges (50-200 lines) connecting Subscribable<T> to framework reactivity. Peer-depend on core + framework. |
| 4. Middleware | devtools, persist, history, immer, telemetry, tab-sync, server, testing |
Cross-cutting concerns via Middleware<T> hooks. Depend only on core (structural typing for store compatibility). |
| 5. Platform Backends | persist-redis |
Platform-specific storage adapters. Depend on their parent middleware package. |
Subscribable<T>—{ get(): T; subscribe(cb): () => void }— universal contract implemented by all signals, computed, stores, and atoms. Framework adapters bridge this single interface.Middleware<T>—{ name, init?, onSet?, onGet?, onSubscribe?, onDestroy? }— lifecycle hooks for cross-cutting concerns. Composed into a pipeline aroundsetState.Scope—{ fork(), get(sub), set(signal, value), serialize() }— per-request state isolation for SSR. Each server request gets its own scope.
- Downward only: Higher layers never import from lower layers
- Core is universal: All packages peer-depend on
@stateloom/core - Paradigms are siblings:
store,atom,proxyare independent — share via core primitives only - Middleware uses structural typing: Middleware declares its own
MiddlewareAPI<T>that structurally matches the store's type, avoiding runtime imports of@stateloom/store
signal.set(value) → push dirty marks through dependency graph → endBatch() flushes subscriber notifications → effects re-execute → computed values lazily recompute on next get() → framework adapter schedules re-render.
| Need | Package |
|---|---|
| Raw reactive primitives | @stateloom/core |
| Zustand-like single-object store | @stateloom/store |
| Jotai-like bottom-up atoms | @stateloom/atom |
| Valtio-like mutable proxy | @stateloom/proxy |
| React/Vue/Solid/Svelte/Angular bindings | @stateloom/<framework> |
| Persist to localStorage/IndexedDB | @stateloom/persist |
| Persist to Redis | @stateloom/persist + @stateloom/persist-redis |
| Redux DevTools integration | @stateloom/devtools |
| Undo/redo | @stateloom/history |
| Mutable update syntax (Immer) | @stateloom/immer |
| Cross-tab sync | @stateloom/tab-sync |
| Analytics/telemetry | @stateloom/telemetry |
| SSR scope management | @stateloom/server |
| Test utilities (mocks, scopes) | @stateloom/testing |
| Violation | Fix |
|---|---|
Core importing localStorage or window |
Move to @stateloom/persist or @stateloom/tab-sync |
| Store importing React hooks | Move to @stateloom/react |
| Atom importing from Store | Share via core primitives (Subscribable<T>) |
| Middleware importing framework code | Framework adapter handles integration |
| Adapter implementing business logic | Move to dedicated middleware package |
| Platform backend hardcoded in middleware | Create a separate @stateloom/persist-<platform> package |
Read these documents before implementing any code changes:
docs/contributing/coding-guidelines.md— TypeScript standards, forbidden constructs, naming conventionsdocs/contributing/testing-guidelines.md— Coverage targets, test patterns, running testsdocs/architecture/layer-scoping.md— Package boundaries, what each layer owns, dependency rulesdocs/architecture/architecture-overview.md— Dependency graph, build order, key interfaces (Subscribable<T>,Middleware<T>,Scope)docs/research/state-management-research.md— Architecture context and competitive analysisdocs/architecture/<package>-design.md— Read the design doc for the specific package you are modifying (e.g.,core-design.md,store-design.md,react-design.md)
Read these documents before writing or updating any documentation:
docs/contributing/documentation-guidelines.md— Writing style, VitePress, Mermaid standards, document structuredocs/architecture/design-philosophy.md— Core design principles and rationale
docs/contributing/testing-guidelines.md— Testing standards (95% coverage target, patterns, type testing)
Available skills are defined in .claude/skills/:
| Command | Skill File | Purpose |
|---|---|---|
/write-code |
.claude/skills/write-code.md |
Implement new features or packages |
/review-code |
.claude/skills/review-code.md |
Review and refactor existing code |
/write-tests |
.claude/skills/write-tests.md |
Write or expand test coverage |
/write-docs |
.claude/skills/write-docs.md |
Write new documentation pages |
/update-docs |
.claude/skills/update-docs.md |
Update existing documentation |
/review-package |
.claude/skills/review-package.md |
Comprehensive package audit (code, tests, perf, DX) |
When executing a skill, read the skill file first, then follow its Required Reading and Workflow sections.
- No enums — use
as constobjects with derived types - No
any— useunknownwith type guards - No default exports — named exports only
import typefor type-only imports (enforced byverbatimModuleSyntax)- No TypeScript-only runtime features — no
namespace, no parameter properties, noabstract class
- Every code change must include tests
- 95% coverage target (statements, branches, functions, lines)
- After writing code, always run:
pnpm turbo run typecheck lint test build --filter=@stateloom/<package> - Fix failures before completing — do not leave broken tests
- Dependencies flow downward only — never import from a higher layer
- Core has zero platform APIs — no
window,localStorage,BroadcastChannel - All packages peer-depend on
@stateloom/core - Framework adapters peer-depend on their framework
- Every exported function, interface, and type must have JSDoc — this is mandatory, not optional
- JSDoc must include: summary,
@param,@returns, and at least one@example - Use
@remarksfor behavioral details (equality semantics, scheduling, cleanup) - Internal functions need a one-line
/** ... */summary (no@examplerequired) - JSDoc is the in-editor documentation — it should be sufficient to understand usage without reading docs site
- When changing code in any package, identify all dependent packages and examples that may need updates. Check and fix tests, docs, and examples for any package that imports from the changed package.
- After any version bump, run
pnpm sync-example-versionsto update@stateloom/*dependency versions in example projects. Examples use real npm version ranges (notworkspace:^) so StackBlitz demos work.
- Use Mermaid for all diagrams
- Code examples must compile and be copy-pasteable
- Consumer perspective — document what developers need, not internals
- Documentation must accompany code changes — when a package is created or updated, the corresponding documentation in
docs/api/<package>/must be created or updated in the same change - Each package must have comprehensive documentation covering: guide (how to use), API reference (every exported function/type), patterns (common usage), and internals (how it works)
# Build
pnpm build # build all
pnpm turbo run build --filter=@stateloom/core # build one package
# Test
pnpm test # test all
pnpm turbo run test --filter=@stateloom/core # test one package
pnpm turbo run test --filter=@stateloom/core -- --coverage # with coverage
# Lint & Type Check
pnpm lint # lint all
pnpm typecheck # typecheck all
# Format
pnpm format # format all files
# Version Sync
pnpm sync-example-versions # sync example deps after version bump
pnpm sync-example-versions 1.2.0-beta.0 # explicit version overridestateloom/
├── packages/ # All @stateloom/* packages
├── examples/ # Example applications
│ ├── vanilla-js/ # Plain JS/TS usage
│ ├── react-vite/ # React + Vite
│ ├── vue-vite/ # Vue + Vite
│ ├── solid-vite/ # Solid + Vite
│ ├── svelte-vite/ # Svelte + Vite
│ ├── angular/ # Angular
│ └── nextjs-ssr/ # Next.js with SSR
├── docs/ # VitePress docs site (also the source dir)
│ ├── guide/ # Framework adoption guides (getting-started, react-vite, etc.)
│ ├── api/ # Per-package API reference (README.md per package)
│ ├── architecture/ # HLD (design-philosophy, etc.) + LLD (*-design.md per package)
│ ├── contributing/ # Coding, testing, documentation guidelines, tooling, workflow
│ ├── research/ # Competitive analysis and research documents
│ └── proposals/ # Original design proposals (archived reference)
├── .claude/skills/ # AI agent skill definitions
├── scripts/ # Build and utility scripts
└── CLAUDE.md # This file