Thanks for your interest in contributing. This guide covers how to set up the project, the conventions the code follows, and how changes get released.
By participating, you agree to follow the Code of Conduct.
- Report a bug: open an issue using the bug report template. Include a minimal reproduction.
- Suggest a feature: open an issue using the feature request template before writing code, so the design can be discussed first.
- Improve the docs: fixes to READMEs and examples are always welcome.
- Pick an issue: issues labeled
good first issueorhelp wantedare a good place to start. Comment on the issue before starting, so work isn't duplicated.
Security issues must not be reported in public issues. See SECURITY.md.
Prerequisites: Node.js 22 (see .nvmrc) and pnpm 10.
git clone https://github.com/<your-username>/spatial.git
cd spatial
pnpm install
pnpm test| Command | Description |
|---|---|
pnpm test |
Run all tests once (Vitest) |
pnpm test:watch |
Run tests in watch mode |
pnpm typecheck |
Type-check all packages |
pnpm lint |
Run ESLint |
pnpm build |
Build the publishable packages (ESM + CJS + types) |
pnpm dev |
Start the vanilla JS example (Vite) |
pnpm dev:react |
Start the React example (Vite) |
packages/
core/ @spatial-kit/core — scene engine, viewport, selection, events, picking
svg/ @spatial-kit/svg — SVG renderer + DOM event handlers
adapters/
react/ @spatial-kit/react — React adapter (hooks + SpatialCanvas)
examples/
js-vanilla/ vanilla JS example (not published)
react/ React example (not published)
Each package README documents its public API.
- No production dependencies in
@spatial-kit/core,@spatial-kit/svgor@spatial-kit/react. Peer dependencies on other@spatial-kit/*packages and on React are the only exceptions. @spatial-kit/corestays framework-agnostic: no DOM, no browser APIs.- TypeScript strict: no
any, no unused variables (prefix intentionally unused arguments with_). - Branded ids: use
EntityIdandLayerId, never plainstring. - Immutable selection: never mutate the
Setreturned byapplySelection. - Factory functions over classes (
createCore,createEmptyScene). - Comments only when the why is not obvious from the code.
- Formatting: Prettier (single quotes, semicolons, 100-character lines). Run
npx prettier --write <files>on what you changed.
- Tests live in
src/__tests__/*.test.ts(x)inside each package. coretests run in Node;svgandreacttests run in jsdom.- jsdom returns a zero rect from
getBoundingClientRectand does not implementsetPointerCaptureorResizeObserver. Mock them in tests that depend on them. - New features and bug fixes need tests. A bug fix should include a test that fails without the fix.
-
Fork the repository and create a branch from
main(for examplefix/pinch-zoom-originorfeat/rubber-band-selection). -
Make the change, with tests and docs.
-
Add a changeset if the change affects a published package (see below).
-
Make sure everything passes locally:
pnpm typecheck && pnpm test && pnpm lint && pnpm build
-
Open the pull request against
mainand fill in the template. Keep it focused on one change.
CI runs the same checks on every pull request. A maintainer will review it; please be patient and responsive to feedback.
Versioning and changelogs are managed with Changesets. If your change affects a published package, run:
pnpm changesetPick the affected packages and the bump type, and write a short summary for the changelog. Commit the generated file in .changeset/ with your pull request.
While the packages are on 0.x:
patch: bug fixes and internal changesminor: new features and breaking changes
Changes to docs, tests, examples or tooling don't need a changeset.
After merge, a bot opens a "version packages" pull request. When a maintainer merges it, the packages are published to npm automatically.
By contributing, you agree that your contributions will be licensed under the MIT License.