Skip to content

Latest commit

 

History

History
199 lines (149 loc) · 12.6 KB

File metadata and controls

199 lines (149 loc) · 12.6 KB

StateLoom — Claude Configuration

This file configures Claude for working on the @stateloom/* monorepo.

Project Overview

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).

Architecture Summary

5-Layer Architecture

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.

Key Interfaces

  • 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 around setState.
  • Scope{ fork(), get(sub), set(signal, value), serialize() } — per-request state isolation for SSR. Each server request gets its own scope.

Dependency Rules

  • Downward only: Higher layers never import from lower layers
  • Core is universal: All packages peer-depend on @stateloom/core
  • Paradigms are siblings: store, atom, proxy are 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

Reactive Data Flow

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.

Package Decision Matrix

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

Common Architecture Violations

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

Required Reading by Task Type

Before Writing Code

Read these documents before implementing any code changes:

  1. docs/contributing/coding-guidelines.md — TypeScript standards, forbidden constructs, naming conventions
  2. docs/contributing/testing-guidelines.md — Coverage targets, test patterns, running tests
  3. docs/architecture/layer-scoping.md — Package boundaries, what each layer owns, dependency rules
  4. docs/architecture/architecture-overview.md — Dependency graph, build order, key interfaces (Subscribable<T>, Middleware<T>, Scope)
  5. docs/research/state-management-research.md — Architecture context and competitive analysis
  6. docs/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)

Before Writing Documentation

Read these documents before writing or updating any documentation:

  1. docs/contributing/documentation-guidelines.md — Writing style, VitePress, Mermaid standards, document structure
  2. docs/architecture/design-philosophy.md — Core design principles and rationale

Before Writing Tests

  1. docs/contributing/testing-guidelines.md — Testing standards (95% coverage target, patterns, type testing)

Skills

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.

Critical Rules

TypeScript

  • No enums — use as const objects with derived types
  • No any — use unknown with type guards
  • No default exports — named exports only
  • import type for type-only imports (enforced by verbatimModuleSyntax)
  • No TypeScript-only runtime features — no namespace, no parameter properties, no abstract class

Testing

  • 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

Architecture

  • 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

Code Documentation (JSDoc)

  • 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 @remarks for behavioral details (equality semantics, scheduling, cleanup)
  • Internal functions need a one-line /** ... */ summary (no @example required)
  • JSDoc is the in-editor documentation — it should be sufficient to understand usage without reading docs site

Cascading Updates

  • 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-versions to update @stateloom/* dependency versions in example projects. Examples use real npm version ranges (not workspace:^) so StackBlitz demos work.

Documentation

  • 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)

Monorepo Commands

# 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 override

Project Structure

stateloom/
├── 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