Thanks for your interest in contributing! We welcome all kinds of contributions — bug fixes, new features, documentation, and ideas.
- Bun 1.3+
- Node.js 22.23.4 or later on 22.x, 24.22.1 or later on 24.x, or 26.12.1 or later (Node 23 and 25 are not supported)
git clone https://github.com/pascalorg/editor.git
cd editor
bun install
bun devThe editor will be running at http://localhost:3002. That's it!
Copy .env.example to .env and add a Google Maps API key if you want address search functionality. The editor works fully without it.
We use Biome for linting and formatting. Before submitting a PR:
bun check # Check for issues
bun check:fix # Auto-fix issues
bun run ci # Everything the CI quality job runs: lint, skills, types, tests, buildbun install points git at .githooks/: the pre-commit hook runs Biome on staged files (and fixes what it can), and the pre-push hook lints and runs check-types and tests for the packages your branch changes. Skip once with --no-verify.
Run the whole suite from the repo root:
bun run test # every package, via TurborepoRun one package while you work on it:
bun --cwd packages/core run testUse bun run test, not bare bun test. test is one of Bun's own
subcommands, so bun test never reaches the package script — it runs Bun's
collector over every file it can find, including compiled copies under dist/,
and reports inflated counts. bun run test goes through Turborepo, which
builds workspace dependencies first (several packages import theirs from
dist/) and runs each package's own scoped test script.
Every string a person reads in the editor (labels, tooltips, aria-label,
title, placeholders, menus, dialogs, errors) goes through the i18n catalog:
const i18n = usePascalI18n()
<button title={i18n._({ id: 'app.editorNavbar.share', message: 'Share' })} />bun run i18n:check (part of bun run ci) fails when a file gains a
hardcoded user-visible literal. Run bun run i18n:extract after changing copy.
Scene data, MCP/agent text and developer errors stay English. See
i18n/README.md for catalogs, translation review, the
migration codemod and the pseudo-locale screenshot audit.
| Package | What it does |
|---|---|
packages/core |
Scene schema, state management, systems — no UI |
packages/viewer |
3D rendering with React Three Fiber |
apps/editor |
The full editor app (Next.js) |
A key rule: packages/viewer must never import from apps/editor. The viewer is a standalone component; editor-specific behavior is injected via props/children.
New node kinds and sidebar panels can ship as a plugin instead of editing the built-ins. Read Create a plugin for the contract, and clone pascalorg/plugin-trees as a worked example.
- Fork the repo and create a branch from
main - Make your changes and test locally with
bun dev - Run
bun run cito make sure linting, types, tests and the build pass - Open a PR with a clear description of what changed and why
- Link related issues if applicable (e.g., "Fixes #42")
- Keep PRs focused — one feature or fix per PR
- Include screenshots or recordings for visual changes
- If you're unsure about an approach, open an issue or discussion first
Maintainers release every @pascal-app/* package together from the Release workflow; contributors never bump versions in a PR. Two things a PR can change need a maintainer before the next release:
-
A new package. Add it to
PACKAGESin.github/workflows/release.yml, then a maintainer publishes it to npm once by hand and adds its trusted publisher. Until then the workflow fails at its first step, before anything is published:cd packages/<pkg> && bun run build && npm publish --access public --tag latest --ignore-scripts
-
The release push. The release commit and tags go to
mainwith theRELEASE_DEPLOY_KEYdeploy key, the one identity besides admins that themainruleset lets through. Keep it in the ruleset's bypass list when the ruleset changes.
Releasing to npm has the trusted-publisher settings, key rotation and recovery steps.
Use the Bug Report template. Include steps to reproduce — this helps us fix things faster.
Use the Feature Request template, or start a Discussion if you want to brainstorm first.
Head to Discussions — we're happy to help!