Skip to content

Contributing

We welcome contributions of all kinds — bug fixes, new shape libraries, documentation improvements, and feature work.

Quick Start

  1. Fork the repository on GitHub
  2. Clone your fork and set up the dev environment (see Project Setup)
  3. Create a feature branch: git checkout -b my-feature
  4. Make your changes
  5. Run checks: task check (or bun run typecheck && bun run test --run)
  6. Commit and push
  7. Open a pull request against master

Code Style

Diagrammer follows these conventions — CI will catch violations, but knowing them upfront saves time:

TypeScript

RuleRationale
No any typesUse unknown with type guards instead
Immutable updatesAll state mutations go through Immer
Pure functionsShape handlers and math utilities should have no side effects
Small, focused filesOne clear responsibility per file
Explicit over cleverVerbose, readable code beats clever one-liners

Rust

The Tauri backend follows standard Rust conventions — cargo fmt and cargo clippy should pass cleanly.

Comments

Only comment code that needs clarification. Don't comment the obvious. Good function and variable names should make intent clear.

What to Work On

Good First Issues

Look for issues labeled good first issue on GitHub.

Shape Libraries

Adding new shape libraries is one of the easiest ways to contribute:

  1. Create a new file under /src/shapes/library/
  2. Define shape handlers (render, hitTest, getBounds, getHandles, create)
  3. Register with ShapeRegistry
  4. Add metadata to ShapeMetadata.ts for the PropertyPanel
  5. Add tests

Documentation

Documentation lives in /docs-site/. It uses VitePress. Run the docs locally:

bash
cd docs-site
bun install
bun run dev

Testing Requirements

All pull requests must pass:

  1. TypeScript type checkingbun run typecheck
  2. All existing testsbun run test --run
  3. Rust compilationcargo check --manifest-path src-tauri/Cargo.toml

Writing Tests

  • Test files go alongside their source file with .test.ts suffix
  • Use Vitest globals (describe, it, expect) — no imports needed
  • Always test math — geometry, coordinate, and transform functions require thorough unit tests
  • Test stores by verifying state transitions, not internal implementation
typescript
describe('MyFeature', () => {
  it('should do the expected thing', () => {
    const result = myFunction(input);
    expect(result).toBe(expected);
  });
});

Architecture Decisions

Before making significant architectural changes, please open an issue to discuss. Key constraints to keep in mind:

  • Canvas rendering is not React — don't introduce React into the render loop
  • Shapes are data, not classes — the ShapeRegistry pattern is intentional
  • DocumentStore is the single source of truth — don't cache shape data elsewhere
  • Camera owns all coordinate math — never manually apply pan/zoom

See Architecture and Core Systems for deeper context.

Commit Messages

Use conventional-ish commit messages:

feat: add swimlane shape to UML library
fix: connector routing ignores rotated shapes
docs: update collaboration setup guide
test: add tests for SpatialIndex edge cases
refactor: extract connector routing into separate module

TIP

Found a bug or have a feature request? Open an issue on GitHub — even if you're not planning to fix it yourself.