Files
backspace/CONTRIBUTING.md
T
Jannis Braun 9d3f72be75 chore: pin Node 20 (LTS) and pnpm 10.34.3
Unpinned `pnpm@latest` in the Dockerfile made fresh builds non-reproducible:
`latest` now resolves to pnpm 11, but the committed lockfile targets pnpm 10, so
`pnpm install --frozen-lockfile` fails with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH on
a clean host. Pin pnpm to 10.34.3 across the Dockerfile, the `packageManager`
field, and the release workflow; pin Node to 20 (LTS) via `.nvmrc` and `engines`
so Docker, CI, and from-source builds all use the same tested toolchain.

Also corrects the docs: the lockfile is v9.0 (requires pnpm 10, not "pnpm 8+"),
and "Node 20+" implied untested newer majors were supported.
2026-07-06 01:04:59 +02:00

4.7 KiB

Contributing to Backspace

Thanks for considering a contribution! Backspace is free and open source software (GNU AGPL-3.0, with a commercial dual-license option), and contributions of all sizes are welcome — bug reports, fixes, features, documentation, and design.

Before you start

  • Read the architecture docs. The docs/systems/ directory documents every subsystem (database, API, WebSocket protocol, federation, permissions, voice, design system, and more). Read the relevant spec before changing a subsystem, and update it in the same pull request if your change is structural.
  • Open an issue first for anything non-trivial. It saves you from building something that conflicts with planned direction. Small fixes can go straight to a pull request.
  • One logical change per pull request. Keep diffs focused and reviewable.

Contributor License Agreement (required)

Before your first contribution can be merged, you must sign the project's Contributor License Agreement.

Backspace is a single-owner project. Under the CLA you keep the copyright to your contribution and grant the maintainer (Jannis Braun) an exclusive, sublicensable license to it — which is what lets the project be offered under both the AGPL and a commercial license. In return, you receive a perpetual license to reuse the specific code you authored in your own other projects (see CLA §5). You also confirm that you have the right to contribute the code in the first place.

Signing is automatic and takes one comment:

  1. Open your pull request.

  2. The CLA bot will comment with a link to the agreement and ask you to sign.

  3. Reply on the pull request with exactly:

    I have read the CLA Document and I hereby sign the CLA

  4. The bot records your signature against your GitHub username. You only sign once — it covers all of your future contributions.

Development setup

Requirements: Node.js 20 (LTS) and pnpm 10. Run nvm use (reads .nvmrc); Corepack activates the pinned pnpm from the packageManager field automatically — don't install pnpm globally.

pnpm install          # install all workspace dependencies
cp .env.example .env  # then set JWT_SECRET (openssl rand -hex 32)
pnpm dev              # API server on :3005, Vite dev server on :5173

You can run the two halves separately with pnpm dev:server and pnpm dev:web.

Voice and video are optional and require a LiveKit server; see the README for configuration. Text, federation, uploads, and everything else run fully without it.

Coding standards

  • TypeScript strict mode, no any. The codebase compiles cleanly under strict settings — keep it that way.
  • Match the surrounding code. Follow existing patterns, naming, and module boundaries rather than introducing new ones.
  • Federation-aware. Never assume a single global user ID. Resolve the correct federated identity for the relevant instance when comparing IDs, checking permissions, or talking to remote servers. See docs/systems/federation.md and docs/systems/client-federation.md.
  • Design system. UI work follows the "Aether Drift" design system documented in docs/systems/design-system.md.
  • No new dependencies without justification. Prefer the existing stack. New dependencies must be permissive (MIT/ISC/Apache-2.0/BSD), or weak-copyleft (LGPL/MPL) only when dynamically linked at arm's length. Never add strong copyleft (GPL/AGPL) or non-permissive licenses (SSPL, BUSL/BSL, non-commercial): strong copyleft cannot ship in the commercial edition, and the others are incompatible with AGPL-3.0-only.
  • Complete implementations only. No placeholder code, no TODO stubs, no partial components. Handle the error and edge cases.

Before you open a pull request

  • pnpm build succeeds (shared types, server, and web all build).
  • The dev server and web client both start without errors (pnpm dev).
  • Tests pass (pnpm test where applicable to the package you touched).
  • You updated the relevant docs/systems/ spec if your change altered schema, API routes, WebSocket events, the federation protocol, permissions, or the design system.

Reporting bugs and requesting features

Use GitHub Issues. For bugs, include reproduction steps, expected vs. actual behavior, and your environment (deployment method, browser/desktop, and whether federation or voice is involved). For security issues, please do not open a public issue — see SECURITY.md.

License

By contributing, you agree that your contributions are licensed under the GNU AGPL-3.0 and are subject to the CLA — an exclusive-license grant that also enables the project's commercial dual-license.