Contributor Guide
- Prerequisites
- Setup
- Project Structure
- Development Workflow
- Testing & Linting
- Code Style
- Branching & Commits
- CI/CD
- Architecture Overview
Prerequisites
- Node.js v20 or later
- corepack enabled:
corepack enable - VS Code
The webview dev:* scripts (standalone browser preview) use portless, which is installed automatically as a dev dependency by yarn install — no global install required.
Setup
yarn installProject Structure
This is a Yarn 4 workspace monorepo containing a single VS Code extension (Camunda Modeler) and its supporting packages:
| Workspace | Path | Description |
|---|---|---|
vs-code-bpmn-modeler | apps/modeler-plugin | VS Code extension host (Node/Webpack) |
@miragon/bpmn-modeler-webview | apps/bpmn-webview | BPMN editor UI (Vite/browser) |
@miragon/dmn-modeler-webview | apps/dmn-webview | DMN editor UI (Vite/browser) |
@miragon/bpmn-modeler-shared | libs/shared | Shared message types and utilities |
Workspace dependencies
Every workspace declares its own runtime and build dependencies in its own package.json. The root package.json only carries cross-cutting tooling (eslint, prettier, npm-run-all, typescript). This lets CI install just the tree it needs via yarn workspaces focus:
# Modeler-only tree (no Theia, no native-keymap, no apt-step required)
yarn workspaces focus bpmn-modeler vs-code-bpmn-modeler @miragon/bpmn-modeler-webview \
@miragon/dmn-modeler-webview @miragon/bpmn-modeler-deployment-webview @miragon/bpmn-modeler-shared @miragon/bpmn-modeler-append-menu \
@miragon/bpmn-modeler-clipboard @miragon/bpmn-modeler-i18n \
@miragon/bpmn-modeler-element-template-chooser \
@miragon/create-append-c7-element-templates
# Just the c7 npm lib
yarn workspaces focus bpmn-modeler @miragon/create-append-c7-element-templates
# Just the docs site
yarn workspaces focus bpmn-modeler docs
# Full repo (needed for the standalone Theia app)
yarn installThe standalone app (apps/standalone) pulls Theia + native-keymap, whose node-gyp postinstall needs libx11-dev libxkbfile-dev libsecret-1-dev on Linux — which is why only the full-install workflow (build.yml) runs the apt-step.
Development Workflow
Build
# Build everything (libs → webviews + plugin in parallel)
yarn build
# Build only the shared libraries
yarn build:libsWatch mode
# Rebuild all workspaces on change (feeds the F5 Extension Host)
yarn watchDocs site
yarn docs:devOpens the VitePress docs site in your browser.
Run the extension in VS Code
- Open the repository root in VS Code.
- Run
yarn watchto start watch mode. - Open the Run and Debug panel and select "Run modeler-plugin".
- Press F5 to launch the Extension Development Host.
To reload the extension host after a change, press Cmd+R (macOS) or Ctrl+R ( Windows/Linux).
Target a single workspace
yarn workspace vs-code-bpmn-modeler build
yarn workspace @miragon/bpmn-modeler-webview buildPreview the BPMN webview in a plain browser
The BPMN webview can run standalone against a mocked VS Code host. This avoids reloading the Extension Development Host while iterating on webview UI.
yarn dev:bpmn-webviewThis launches a Vite dev server via portless; the URL is printed to stdout when the server starts.
A URL query parameter selects what the mock serves:
| URL | What renders |
|---|---|
/ (or ?mode=modeler) | Full editable Camunda modeler with a hardcoded sample diagram — matches the production modeler experience. |
/?mode=diff-before | Readonly before (left) pane of a diff view, with highlights for removed / changed / moved elements. |
/?mode=diff-after | Readonly after (right) pane, with highlights for added / changed / moved elements. |
The diff modes run bpmn-js-differ against two fixture XMLs (apps/bpmn-webview/src/app/__fixtures__/mock-diff.ts) so highlights reflect the real differ's output. All mock code and its dependencies are gated on NODE_ENV === "development" and tree-shaken out of the production webview bundle.
Testing & Linting
# Run all tests (includes coverage by default)
yarn test
# Run a single test file
yarn test --testPathPattern=apps/modeler-plugin/src/service/bpmnUtils.spec.ts
# Lint
yarn lintCoverage reports are uploaded to Codecov on CI.
Code Style
| Tool | Configuration | Key rules |
|---|---|---|
| EditorConfig | .editorconfig | 4-space indent, LF line endings, max 89 chars |
| Prettier | .prettierrc | Double quotes, trailing commas, arrow parens always |
| ESLint | eslint.config.mjs | TypeScript strict |
Prettier and ESLint are enforced by the lint step in CI.
Branching & Commits
Branching model
Commit messages
Use semantic commit messages scoped to the affected workspace:
feat(bpmn): add token simulation toolbar
fix(dmn): correct decision table rendering
chore(shared): update message type definitionsCommon types: feat, fix, refactor, chore, docs, test.
CI/CD
| Workflow | Trigger | Purpose |
|---|---|---|
| Build | every push / PR | lint → test → build, full install (apt-step for Theia native modules) |
| PR Labeler | PR opened / updated | auto-labels PRs by changed workspace |
| **Prepare Release *** | manual (workflow_dispatch) | bump version, sanity build, commit, tag, create GitHub Release |
| **Publish *** | release: published (or workflow_dispatch + dry-run) | build artefact, attach to release, push to Marketplace / npm / GitHub Release |
| Deploy Docs | release: published / manual | VitePress build + GitHub Pages deploy |
There are three prepare-* and three publish-* workflows — one pair per artefact (VS Code extension, c7 npm lib, standalone macOS app). See Release process for the operational guide and the pipeline flow diagram.
Architecture Overview
The extension uses a flat service architecture with plain constructor wiring — no DI framework.
apps/modeler-plugin/src/
domain/ # Pure domain types — no external dependencies
infrastructure/ # VS Code API adapters (EditorStore, VsCodeDocument, …)
service/ # Business logic (BpmnModelerService, ArtifactService, …)
controller/ # VS Code events → service calls
main.ts # Wiring: EditorStore → VsCode* → Services → ControllersKey design decisions:
- Echo prevention: each open editor gets a
ModelerSessionguard that blocks theonDidChangeTextDocumentecho caused by the extension's own document write. - Element template discovery: convention-based — no project config file needed. Templates are resolved under
<configFolder>/element-templates/walking up from the BPMN file to the workspace root. - Webview communication:
postMessagewith typed message contracts defined inlibs/shared.
See CLAUDE.md in the repository root for the full architectural reference.