Skip to content

Contributing to StateLoom

Guide for setting up the development environment, making changes, and submitting contributions.

Prerequisites

ToolVersionInstall
Node.js20+nvm install 20
pnpm9+corepack enable && corepack prepare pnpm@latest --activate
Git2.30+System package manager

Setup

bash
git clone https://github.com/stateloom/stateloom.git
cd stateloom
corepack enable
pnpm install
pnpm build          # build all packages in dependency order
pnpm test           # run all tests

Verify everything works before making changes.

Development Workflow

Working on a Package

bash
# Build and watch a specific package
pnpm turbo watch build --filter=@stateloom/core

# Run tests for a specific package
pnpm turbo run test --filter=@stateloom/core

# Run tests in watch mode
pnpm turbo run test:watch --filter=@stateloom/core

# Type check a specific package
pnpm turbo run typecheck --filter=@stateloom/core

Working with Examples

bash
# Start React Vite example (with hot reload)
pnpm dev:react-vite

# Start Next.js App Router example
pnpm dev:next-app

Full Validation

Before submitting any changes, run:

bash
pnpm lint           # lint all packages
pnpm typecheck      # type check all packages
pnpm build          # build all packages
pnpm test           # run all tests

All four must pass.

Making Changes

Branch Naming

feat/<description>     # new features
fix/<description>      # bug fixes
refactor/<description> # refactoring
docs/<description>     # documentation only
test/<description>     # test changes only

Commit Convention

Use Conventional Commits:

feat(core): add custom equality comparator to signal
fix(react): prevent double-render in StrictMode
docs(store): add middleware composition example
test(atom): add diamond dependency test case
refactor(proxy): extract snapshot logic to separate module
chore: update pnpm to 9.15

Format: <type>(<scope>): <description>

  • type: feat, fix, docs, test, refactor, chore, perf
  • scope: package name without @stateloom/ prefix (e.g., core, react, store)
  • description: imperative mood, lowercase, no period

Code Standards

All code must follow the Coding Guidelines. Key rules:

  • Strict TypeScript — no any, no enums, import type for types
  • Named exports only
  • 95%+ test coverage for every package
  • No console.log in library code

Testing Requirements

Every code change must include tests:

  1. Write tests alongside code changes
  2. Run pnpm turbo run test --filter=@stateloom/<package> -- --coverage
  3. Ensure 95%+ coverage (statements, branches, functions, lines)
  4. Include type tests using expectTypeOf for public API changes

Documentation Updates

If your change affects public API:

  1. Update the relevant package README in docs/api/
  2. Update code examples to reflect new behavior
  3. Update Mermaid diagrams if architecture changed

Changeset Workflow

StateLoom uses Changesets for versioning and publishing.

When You Change Published Code

bash
pnpm changeset

This prompts you to:

  1. Select which packages changed
  2. Choose version bump type (patch, minor, major)
  3. Write a description of the change

A changeset file is created in .changeset/. Commit it with your changes.

What Gets a Changeset

Change TypeNeeds Changeset
Bug fix in published packageYes (patch)
New feature in published packageYes (minor)
Breaking change in published packageYes (major)
Test-only changesNo
Documentation-only changesNo
Example app changesNo
CI/tooling changesNo

Release Process

Releases are automated via GitHub Actions:

  1. Changesets accumulate on main
  2. The Changesets GitHub Action opens a "Version Packages" PR
  3. Merging that PR triggers pnpm changeset publish → npm publish

Syncing Example Versions

Examples use real npm version ranges (not workspace:^) so that StackBlitz can load them directly from the repo. After bumping package versions, sync the examples:

bash
pnpm sync-example-versions              # reads version from packages/core
pnpm sync-example-versions 1.2.0-beta.0 # explicit version override

This must be run after every version bump. Forgetting this step will break StackBlitz demos.

Adding a New Package

bash
pnpm new-package    # interactive scaffold

This generates:

  • packages/<name>/src/index.ts
  • packages/<name>/__tests__/
  • packages/<name>/package.json (with correct exports, peer deps)
  • packages/<name>/tsconfig.json
  • packages/<name>/tsup.config.ts
  • packages/<name>/vitest.config.ts

After scaffolding:

  1. Implement the feature in src/
  2. Write tests in __tests__/
  3. Create documentation in docs/api/<name>/README.md
  4. Run full validation: pnpm lint && pnpm typecheck && pnpm build && pnpm test

CI Pipeline

Every PR runs:

StepCommandPurpose
Lintpnpm lintESLint + Prettier
Type Checkpnpm typecheckTypeScript strict mode
Buildpnpm buildtsup (ESM + CJS + dts)
Testpnpm testVitest with coverage
Size Checkpnpm sizeBundle size budget

All steps must pass for the PR to be mergeable.

Architecture Reference

Before contributing, familiarize yourself with: