Contributing
We welcome contributions of all kinds — bug fixes, new shape libraries, documentation improvements, and feature work.
Quick Start
- Fork the repository on GitHub
- Clone your fork and set up the dev environment (see Project Setup)
- Create a feature branch:
git checkout -b my-feature - Make your changes
- Run checks:
task check(orbun run typecheck && bun run test --run) - Commit and push
- Open a pull request against
master
Code Style
Diagrammer follows these conventions — CI will catch violations, but knowing them upfront saves time:
TypeScript
| Rule | Rationale |
|---|---|
No any types | Use unknown with type guards instead |
| Immutable updates | All state mutations go through Immer |
| Pure functions | Shape handlers and math utilities should have no side effects |
| Small, focused files | One clear responsibility per file |
| Explicit over clever | Verbose, 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:
- Create a new file under
/src/shapes/library/ - Define shape handlers (render, hitTest, getBounds, getHandles, create)
- Register with
ShapeRegistry - Add metadata to
ShapeMetadata.tsfor the PropertyPanel - Add tests
Documentation
Documentation lives in /docs-site/. It uses VitePress. Run the docs locally:
cd docs-site
bun install
bun run devTesting Requirements
All pull requests must pass:
- TypeScript type checking —
bun run typecheck - All existing tests —
bun run test --run - Rust compilation —
cargo check --manifest-path src-tauri/Cargo.toml
Writing Tests
- Test files go alongside their source file with
.test.tssuffix - 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
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 moduleTIP
Found a bug or have a feature request? Open an issue on GitHub — even if you're not planning to fix it yourself.