First — thank you for your interest in contributing to the BESSER Web Modeling Editor (WME)! ❤️
This repository hosts the WME frontend (webapp + standalone server) and the
core diagramming engine (packages/editor, published as @besser/wme). The
BESSER backend (metamodels, generators, editor backend) lives in
BESSER-PEARL/BESSER, and this repo
is also vendored into the backend as a git submodule at
besser/utilities/web_modeling_editor/frontend.
This guide explains how to get set up, how we collaborate, and what we expect from every contribution.
- Contributing to the BESSER Web Modeling Editor
- 📑 Table of Contents
- 📋 Before You Start
- 🤝 Ways to Contribute
- 🧠 Asking Questions
- 🐞 Reporting Issues & Requesting Features
- 🍴 Setting Up Your Development Environment
- 🗂️ Repository Tour
- 💻 Development Guidelines
- ✅ Testing Your Changes
- 🧾 Documentation Updates
- 🌿 Branching & Commits
- 🔀 Creating Pull Requests
- 🔗 Cross-Repo Changes (BESSER Backend)
- 🧭 Governance
- 💖 Thank You!
- Read and follow our Code of Conduct.
- Familiarize yourself with the project governance model.
- Skim the WME documentation site for background and editor concepts.
- Try the live editor at https://editor.besser-pearl.org/ to understand the end-user experience before changing it.
You don't need to be a TypeScript expert to help. Useful contributions include:
- Code — new diagram types, editor improvements, UI features, bug fixes, performance work, refactors.
- Documentation — clarifying existing pages under
docs/source/, fixing typos, writing tutorials, adding screenshots. - Tests — improving Vitest unit coverage and Playwright end-to-end scenarios.
- Issue triage — reproducing reported bugs, narrowing down causes, suggesting workarounds.
- Feedback — sharing how you use the editor, what is missing, what is confusing. Open an issue or discussion.
- Translations — adding or improving locale files in
packages/editor/src/main/i18n/.
If you are looking for a starting point, browse issues labeled
good first issue
or help wanted.
Have a question?
- For usage or design questions, open an issue or comment on an existing ticket.
- For private inquiries, email info@besser-pearl.org.
Please write clear, concise messages — the more detail you provide (browser, OS, WME version, expected vs. actual behavior), the easier it is to help.
Found a bug or have a feature idea? We want to hear it.
- Search first. Check the issue list to avoid duplicates.
- One topic per issue. Mixing concerns slows triage.
- Include reproduction details:
- Steps to reproduce
- Expected vs. actual behavior
- Browser, OS, and WME version (or commit hash if running locally)
- Screenshots, screen recordings, or links to the model that triggers the issue
- Console errors and network failures from DevTools
- Explain the impact. Knowing why the change matters helps prioritize.
For feature requests, describe the use case, not just the implementation — that opens room for the best design.
- Node.js 20+ and npm (CI runs on Node 20).
- Git.
- A running BESSER backend for full functionality (code generation, validation, deployment). The editor itself runs without it for pure diagramming work, but most "Generate / Validate / Deploy" flows need it.
-
Fork this repository to your GitHub account.
-
Clone your fork:
git clone https://github.com/<your-username>/BESSER-Web-Modeling-Editor.git cd BESSER-Web-Modeling-Editor
-
Add the upstream remote so you can keep your fork in sync:
git remote add upstream https://github.com/BESSER-PEARL/BESSER-Web-Modeling-Editor.git
-
Install dependencies from the monorepo root:
npm install
This installs all workspaces (
webapp,editor,server) in one go.
npm run devThe Vite dev server runs on http://localhost:8080 and expects the BESSER
backend at http://localhost:9000/besser_api in development mode (see
packages/webapp/src/main/constants/constant.ts).
To run the BESSER backend locally, follow its setup instructions and start it with:
python besser/utilities/web_modeling_editor/backend/backend.py| Command | Purpose |
|---|---|
npm run dev |
Start webapp with Vite + HMR |
npm run build |
Build webapp + standalone server |
npm run build:webapp |
Build webapp only |
npm run build:local |
Build with localhost backend URLs |
npm run start:server |
Serve the built webapp via the Express server |
npm run lint |
ESLint across workspaces |
npm run prettier:check / prettier:write |
Check / auto-format with Prettier |
npm run test |
Vitest unit tests (webapp) |
npm run test:e2e |
Playwright end-to-end tests |
npm run test:e2e:ui |
Playwright with interactive UI |
Per-workspace variants are available via --workspace=<name> (e.g.,
npm run lint --workspace=editor).
This is an npm workspaces monorepo with three packages:
| Package | Status | Purpose |
|---|---|---|
packages/webapp |
Active | Main React SPA (Vite + React 18 + Tailwind + Radix UI) |
packages/editor |
Active | Core diagramming engine, published as @besser/wme on npm |
packages/server |
Active | Express server for standalone hosting (serves built webapp) |
Almost all feature work happens in webapp and editor.
| Path | Purpose |
|---|---|
packages/webapp/src/main/app/ |
Shell, routing, Redux store |
packages/webapp/src/main/features/ |
Feature modules (editors, generation, deploy, github, import, …) |
packages/webapp/src/main/shared/ |
Cross-feature code (API client, components, hooks, services) |
packages/editor/src/main/apollon-editor.ts |
Public API of the diagramming engine (ApollonEditor class) |
packages/editor/src/main/packages/ |
Diagram-specific implementations (UML, BPMN, flowchart, …) |
packages/editor/src/main/services/ |
Domain logic (CRUD, undo, layout, collaboration) |
packages/editor/src/main/i18n/ |
Translations |
docs/ |
Sphinx docs published under the BESSER Read the Docs site |
For deeper architecture notes, see
docs/source/contributing/codebase-guide.rst
and the WME architecture page.
- TypeScript strict mode — keep types honest.
anyand@ts-ignoreare warnings, not errors, but minimize their use. - Tailwind CSS for styling in
webapp. No inline styles or CSS modules in webapp. The editor package still uses styled-components (legacy). - Radix UI for accessible primitives (Dialog, DropdownMenu, Tooltip, …). Prefer these over hand-rolled equivalents.
_prefix for intentionally unused variables.- ESLint warnings are acceptable but errors must be fixed.
- Prettier formatting is enforced — run
npm run prettier:writebefore committing.
Features in packages/webapp/src/main/features/ must not import from
each other. If two features need the same logic, lift it into
shared/. Each feature owns its own hooks, components, and dialogs.
Configured in both tsconfig.json and vite.config.ts:
@/→src/@besser/wme→../editor/src/main/index.tsin local dev (npm in production)shared→../shared/src/index.tswebapp/*→./*
If you add a new alias, update both files.
- Project/diagram state lives in a single
workspaceSlice. Use Redux Toolkit async thunks for mutations. - Use
withoutNotify()when writing toProjectStorageRepositoryfrom a thunk to prevent infinite sync loops. - Bump
editorRevisiononly for structural changes (e.g., switching diagram types). Don't bump it for view-only toggles — it clears undo history. - Use the typed hooks
useAppDispatch()anduseAppSelector()fromstore/hooks.ts.
All backend calls go through shared/api/api-client.ts:
- Singleton
apiClientwith a 30 s timeout. - Methods:
get(),post(),upload()(FormData),downloadBlob()(binary). - Custom
ApiErrorclass with HTTP status.
If you change a backend API contract, update both the backend (Pydantic
models / endpoint) and shared/api/ in lock-step.
Register the element in 4 files inside
packages/editor/src/main/packages/:
components.ts—UMLElementType.YourElement→ React render componentuml-elements.ts—UMLElementType.YourElement→ model classcompose-preview.ts— palette previewpopups.ts— property popup component
Then create the implementation in the appropriate diagram package
directory (e.g., packages/uml-class-diagram/your-element/) with:
- A model class extending
UMLElementorUMLRelationship - A React component
- An update function for property changes
- Add an entry to
diagram-type.ts(UMLDiagramTypeobject). - Create a package directory under
packages/editor/src/main/packages/. - Register all elements in the four registry files.
- Add editor support in
packages/webapp/src/main/features/editors/. - Add the diagram type to the BESSER backend's supported types if it needs generation/validation.
A full walk-through is in
docs/source/contributing/new-diagram-guide/.
npm run lint
npm run prettier:checknpm run test --workspace=webappWhile iterating, target a single test file with npm run test -- <pattern>.
npm run test:e2e --workspace=webapp
npm run test:e2e:ui --workspace=webapp # interactiveRun E2E from the webapp workspace, not the monorepo root.
A passing build is part of the contract:
npm run buildGuidelines:
- Add or update tests alongside any behavior change.
- Validate observable behavior, not implementation details. Tests on rendered output age better than tests on internal structure.
- For UI changes, prefer Playwright over hand-clicking — write the scenario down once instead of demonstrating it manually for every reviewer.
User-facing docs live in docs/source/ and are written in
reStructuredText (Sphinx). Keep them in sync with code: a new diagram
type, editor feature, or workflow should be reflected in the docs.
Build locally to check formatting:
cd docs
pip install -r requirements.txt
make html # Linux/macOS
# or:
sphinx-build -b html source build/htmlOpen docs/build/html/index.html to preview.
Common pages to update:
docs/source/editor/— editor features and behaviordocs/source/user-guide/— end-user workflowsdocs/source/webapp/— webapp shell, settings, project hubdocs/source/contributing/— contributor-facing guidesdocs/source/reference/— API / schema references
Place images in docs/source/images/ (or the relevant subfolder) and
reference them with relative paths.
Create a topic branch off develop (the integration branch). Use a
prefix that matches the type of change:
| Prefix | Use for | Example |
|---|---|---|
feature/ |
New features or capabilities | feature/add-petri-net-diagram |
fix/ |
Bug fixes | fix/state-diagram-toolbar-mismatch |
docs/ |
Documentation-only changes | docs/update-contributor-guide |
refactor/ |
Code restructuring without behavior changes | refactor/extract-component-registrar |
test/ |
Test additions or improvements | test/quantum-editor-e2e |
chore/ |
Tooling, CI, dependency bumps, repo maintenance | chore/bump-vite |
Use lowercase, hyphen-separated, descriptive names. Avoid personal
prefixes (arm/...) and avoid umbrella branches that bundle unrelated
changes.
We follow Conventional Commits. Use one of these prefixes in your commit subject:
feat:— a new featurefix:— a bug fixdocs:— documentation-only changesrefactor:— code change that neither fixes a bug nor adds a featuretest:— adding or fixing testschore:— tooling, CI, dependency, or repo-maintenance changes
Keep subjects short, imperative, and lowercase, e.g.:
feat: add petri-net diagram type
fix: prevent infinite sync loop in storage thunk
docs: clarify branch naming in CONTRIBUTING
Group related work into logically scoped commits — reviewers should be able to follow the reasoning commit by commit.
Open all pull requests against
develop, notmain.The
mainbranch tracks released versions of the editor. Thedevelopbranch is where features are integrated and validated before release. Maintainers periodically mergedevelopintomainas part of the release process — contributors should not targetmaindirectly.
When opening the PR on GitHub, the base branch dropdown defaults to
main. Change it to develop before clicking Create pull
request:
base repository: BESSER-PEARL/BESSER-Web-Modeling-Editor base: develop ← change this!
head repository: <your-fork>/BESSER-Web-Modeling-Editor compare: feature/your-change
If you forget, no harm done — just edit the base branch on the existing PR (GitHub allows changing it after creation). Maintainers will also flag it.
-
Sync your fork and branch off
develop:git checkout develop git pull upstream develop git checkout -b feature/your-change
-
Commit your work using the Conventional Commits prefixes. Make focused commits.
-
Run quality checks locally before pushing:
npm run lint npm run prettier:check npm run test --workspace=webapp npm run build -
Push your branch:
git push -u origin feature/your-change
-
Open the PR on GitHub with
developas the base branch (see above). If the work is in progress and you want early feedback, open it as a draft PR — maintainers will review when you mark it ready. -
Rebase or merge
developinto your branch before requesting final review:git fetch upstream git rebase upstream/develop git push --force-with-lease
-
Respond to review feedback. Review is a collaborative conversation, not a gate.
A great PR description answers four questions: What changed? Why? How was it tested? What should reviewers pay attention to? Use this template (the PR template in this repo follows the same structure):
## What
A 1–3 sentence summary of the change. Stay concrete — name the files,
features, components, or diagram types you touched.
## Why
The motivation. Link the issue (`Closes #123`), or describe the bug,
limitation, or use case driving the change. Reviewers should not have
to guess the intent.
## How
A brief explanation of the approach, *especially* for non-obvious design
choices. Mention alternatives you considered and why you discarded them.
Skip this section for trivial fixes.
## Testing
- Unit tests added/updated: `packages/webapp/src/.../foo.test.ts`
- E2E tests added/updated: `packages/webapp/tests/e2e/...`
- Manual checks: e.g., "loaded the editor, created a class diagram with
inheritance, exported, re-imported — round-trip preserved"
- Edge cases considered: …
## Screenshots / Recordings
(For UI changes, include before/after screenshots or short recordings.)
## Follow-ups / Known limitations
Anything intentionally out of scope for this PR, or known gaps to address
later. Linking a follow-up issue is even better.
## Checklist
- [ ] Targeted `develop` (not `main`)
- [ ] `npm run lint` passes
- [ ] `npm run prettier:check` passes
- [ ] `npm run test --workspace=webapp` passes
- [ ] `npm run build` succeeds
- [ ] Docs updated (`docs/source/...`) if user-facing behavior changed
- [ ] Backend submodule pointer updated in BESSER (if cross-repo change)
- [ ] No stray `console.log` or debug code- Title matters. Use a Conventional Commits-style title that mirrors
your main commit, e.g.
feat: add petri-net diagram type. Reviewers scan PR lists by title. - Be specific, not generic. "Fix bug" is not a PR description. "Fix state-diagram toolbar showing object-diagram elements after switching diagram types" is.
- Show, don't tell. UI work without screenshots is much harder to review.
- Call out anything risky. Schema/storage migrations, breaking API changes, dependency bumps, performance trade-offs — flag them explicitly.
- Keep it focused. One PR = one logical change. If you find yourself writing "this PR also …", split it.
- All PRs must pass automated checks: ESLint (webapp + server), Prettier, the production build, and Vitest unit tests.
- At least one maintainer review is required, per the governance rules.
- Maintainers choose the merge strategy (squash, rebase, or merge commit) based on the change.
This repo is vendored into the BESSER backend as a git submodule at
besser/utilities/web_modeling_editor/frontend.
When a change touches both repositories (e.g., a new diagram type, an API contract change):
-
Implement and commit the frontend change here, targeting
develop. -
Implement and commit the backend change in BESSER, targeting
development. -
Update the submodule pointer in the BESSER repo to the new WME commit:
# in the BESSER repo cd besser/utilities/web_modeling_editor/frontend git pull origin develop cd ../../../.. git add besser/utilities/web_modeling_editor/frontend git commit -m "chore: bump frontend submodule"
-
Link the two PRs in their descriptions and note the intended merge order.
When you see M besser/utilities/web_modeling_editor/frontend in the
parent repo's git status, the submodule pointer has moved.
All contributions are reviewed by project maintainers following the rules in GOVERNANCE.md. This ensures fair, transparent decision-making. If a discussion stalls, maintainers will help unblock it.
Your contributions — big or small — make BESSER better. Thank you for your time, energy, and passion for open source.
If anything in this guide is unclear or out of date, that itself is a
great first contribution: open a docs/ PR and propose an improvement.