bpmn-js
A reference guide for working with bpmn-js modeler internals in web applications.
Install
mkdir -p .claude/skills/bpmn-js && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/9618" && unzip -o skill.zip -d .claude/skills/bpmn-js && rm skill.zipInstalls to .claude/skills/bpmn-js
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
bpmn-js modeler internals — EventBus, services, copy-paste architecture, clipboard polyfill, modeler lifecycle. Use when working on bpmn-webview, diagram interactions, copy-paste, clipboard, or element templates.Key capabilities
- →Manage bpmn-js modeler lifecycle
- →Handle diagram event bus
- →Implement clipboard polyfills
- →Configure Camunda engine variants
How it works
It wraps the bpmn-js modeler and manages lifecycle events, clipboard interception, and engine-specific module loading.
Inputs & outputs
When to use bpmn-js
- →Customizing bpmn-js element templates
- →Debugging modeler lifecycle events
- →Implementing custom copy-paste behavior
- →Configuring Camunda engine variants
About this skill
bpmn-js Modeler Internals
This skill covers how the BPMN webview (apps/bpmn-webview/) uses the bpmn-js library to render and edit BPMN diagrams, including the copy-paste architecture and clipboard polyfill.
Modeler Initialization
The modeler is encapsulated in apps/bpmn-webview/src/app/modeler.ts as a BpmnModeler class. It wraps the underlying camunda-bpmn-js modeler (which extends bpmn-js).
Engine Variants
The modeler supports two Camunda engine variants, selected at initialization:
- Camunda 7 — imports
BpmnModeler7fromcamunda-bpmn-js/lib/camunda-platform/Modeler. Additional modules:CreateAppendElementTemplatesModule,TransactionBoundariesModule. - Camunda 8 — imports
BpmnModeler8fromcamunda-bpmn-js/lib/camunda-cloud/Modeler. No extra modules beyond the common set.
Both variants share TokenSimulationModule and ElementTemplateChooserModule as common modules.
Lifecycle
window.onloadinmain.tsregisters the message listener, installs the select-all handler, and initialises the thememain.tssendsGetBpmnFileCommandto the extension host and awaits theBpmnFileQueryresponseinitializeModeler()callsBpmnModeler.create(engine)to mount the modelerBpmnModeler.loadDiagram(xml)imports the BPMN XML- Viewport is restored from
vscode.getState()if available - Event listeners are installed for
commandStack.changedandcanvas.viewbox.changed - The clipboard interceptor and contenteditable polyfill are installed (production only — see below)
- Element templates and modeler settings are requested from the extension host
Modeler Options
The modeler is created with these configuration options (see MODELER_OPTIONS constant):
container:"#js-canvas"— DOM element for the diagram canvaspropertiesPanel.parent:"#js-properties-panel"— DOM element for the properties panel sidebaralignToOrigin:{ alignOnSave: false, offset: 150, tolerance: 50 }— configures the auto-align pluginadditionalModules: Engine-specific modules (see Engine Variants above)
Core bpmn-js Services
Services are accessed via modeler.get('serviceName'). Key services used:
| Service | Purpose |
|---|---|
eventBus | Pub/sub event system — all modeler events flow through this |
copyPaste | Handles element copy/cut/paste operations on the diagram |
moddle | BPMN model factory — used by the paste reviver to reconstruct typed objects |
canvas | Diagram canvas — viewport management, zoom, scroll |
elementTemplatesLoader | Loads element templates from JSON into the modeler |
alignToOrigin | Auto-aligns diagram to canvas origin (configurable) |
transactionBoundaries | Shows/hides transaction boundary overlays (C7 only) |
EventBus Events
Events This Project Listens To
| Event | Where | Purpose |
|---|---|---|
commandStack.changed | modeler.ts | Triggered after any modeler command. Exports XML and sends SyncDocumentCommand to host. |
canvas.viewbox.changed | modeler.ts | Triggered on scroll/zoom. Debounced (100ms), saves viewport to vscode.setState() for persistence. |
copyPaste.elementsCopied | modeler.ts | Triggered when elements are copied. Intercepted to write descriptor JSON to system clipboard via extension host. |
copyPaste.pasteElements | modeler.ts | Triggered when paste occurs. Intercepted to read descriptor JSON from system clipboard via extension host. |
elementTemplates.errors | modeler.ts | Triggered when element template loading produces errors. Forwarded to a callback for error reporting. |
Event Priority System
bpmn-js events use a priority system. Higher priority listeners fire first and can prevent lower-priority listeners from executing by returning false or calling event.stopPropagation().
- Default priority:
1000 - The element-clipboard interceptor in
VsCodeClipboardModuleuses priority2051— intentionally above bpmn-js'sNativeCopyPaste(priority2050) to interceptcopyPaste.elementsCopied/copyPaste.pasteElementsbefore the default handler runs
Copy-Paste Architecture (Three Layers)
Copy-paste in this project operates at three distinct layers. The first two are
bpmn-js DI modules extracted into the shared libs/bpmn-clipboard package
(@miragon/bpmn-modeler-clipboard) and installed as additionalModules in
apps/bpmn-webview/src/main.ts; the third is a webview-local polyfill. The two
DI modules receive their host bridges through didi value injection —
elementClipboardBridge (element JSON) and textClipboardBridge (plain text),
each a { requestClipboard, writeClipboard } pair wired in main.ts to the
host clipboard commands. Because bpmn-js's own NativeCopyPaste still handles
the canvas natively in a plain browser, the interception only matters inside the
sandboxed VS Code / IntelliJ webview, where the iframe has no clipboard access.
Two separate host round-trips: element clipboard uses
GetClipboardCommand/SetClipboardCommand→ClipboardQuery; text clipboard (labels, FEEL editor) usesGetTextClipboardCommand/SetTextClipboardCommand→TextClipboardQuery.
Layer 1: Diagram Elements (VsCodeClipboardModule)
Handles copying/pasting of BPMN shapes and connections on the canvas.
Flow — Copy:
- User presses Cmd/Ctrl+C while diagram elements are selected
- bpmn-js
CopyPastemodule serializes selected elements into a descriptor tree (plain JS objects) copyPaste.elementsCopiedevent fires- Our priority-2051 listener intercepts → prefixes the JSON with
"bpmn-js-clip----"and sends it to the extension host viaSetClipboardCommand - Extension host writes to system clipboard via
vscode.env.clipboard.writeText()
Flow — Paste:
- User presses Cmd/Ctrl+V while canvas is focused
copyPaste.pasteElementsevent fires- If
context.treealready exists (same-editor paste), the interceptor does nothing — bpmn-js handles it internally - Otherwise, the interceptor snapshots the current context, returns
falseto cancel the default paste, and sendsGetClipboardCommandto the extension host - Extension host reads system clipboard → responds with clipboard text via
ClipboardQuery - Listener checks for the
"bpmn-js-clip----"prefix, strips it, and parses the JSON usingcreateReviver(moddle)frombpmn-js-native-copy-paste— this reviver reconstructs typed BPMN model objects from plain JSON - Calls
copyPaste.paste()with the deserialized tree and the snapshotted context
Why snapshot the context? The return false in step 4 sets defaultPrevented: true on the event context object. Without snapshotting first, the async paste callback would inherit this flag, causing copyPaste.paste() to silently abort.
Why the interceptor? The webview runs in an iframe without clipboard API access. The extension host mediates clipboard access via vscode.env.clipboard.
Layer 2: Direct-Editing Label Overlays (LabelClipboardModule)
Handles copying/pasting text within contenteditable label overlays on the diagram canvas (e.g., when double-clicking a task to edit its name). This targets diagram-js's direct-editing overlays, not properties panel inputs — standard INPUT and TEXTAREA elements work natively in VS Code webviews.
Problem: diagram-js's DirectEditing._handleKey calls stopPropagation() on every keydown from the contenteditable overlay. This prevents native clipboard handling from reaching the element. Additionally, VS Code webview iframes lack clipboard-read/clipboard-write permissions.
Solution: LabelClipboardModule is a bpmn-js DI module that attaches a capture-phase keydown listener on the label element, only while direct editing is active (scoped tighter than the old document-wide listener). Capture phase fires before bubble phase, so it runs before diagram-js can stop propagation.
Capture phase (our listener) → Target → Bubble phase (diagram-js listener)
For Cmd/Ctrl+C it reads window.getSelection() and writes via the injected textClipboardBridge.writeClipboard; for Cmd/Ctrl+V it prevents default, reads via textClipboardBridge.requestClipboard, then dispatches a synthetic ClipboardEvent("paste"), falling back to document.execCommand('insertText') if no handler consumes it.
Layer 3: FEEL Editor Polyfill + Select-All Guard (propertiesPanelClipboard.ts)
The C8 properties panel's FEEL expression editor is CodeMirror 6, which lives outside the bpmn-js DI context — so the two DI modules above can't reach it. installContentEditableClipboardPolyfill(requestTextClipboard, writeTextClipboard) (still webview-local in apps/bpmn-webview/src/app/propertiesPanelClipboard.ts, installed from main.ts) fills that gap: a capture-phase keydown listener that bridges Cmd/Ctrl+C/V on any contenteditable/text-editing surface through the host text clipboard.
It also guards Cmd/Ctrl+A: without it, bpmn-js's Keyboard service steals Ctrl+A in a text field and selects all diagram shapes. The polyfill lets Ctrl+A select text within the focused editable element (canvas Ctrl+A stays owned by bpmn-js's SelectionKeyBindings).
Element Templates
Element templates are JSON files that define custom property configurations for BPMN elements. They are loaded by:
- Extens
Content truncated.
When not to use it
- →When working outside of bpmn-webview
- →When not using bpmn-js library
Prerequisites
Limitations
- →Clipboard interception is production-only
How it compares
It provides deep internal access to modeler services and event bus priorities rather than just basic rendering.
Compared to similar skills
bpmn-js side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| bpmn-js (this skill) | 0 | 3mo | Review | Advanced |
| add-announcement | 1 | 7mo | Review | Beginner |
| scroll-experience | 101 | 6mo | No flags | Intermediate |
| anthropic-frontend-design | 12 | 6mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by Miragon
View all by Miragon →You might also like
add-announcement
Agenta-AI
Helps add announcement cards to the sidebar banner system. Use when adding changelog entries, feature announcements, updates, or promotional banners to the Agenta sidebar. Handles both simple changelog entries and complex custom banners.
scroll-experience
davila7
Expert in building immersive scroll-driven experiences - parallax storytelling, scroll animations, interactive narratives, and cinematic web experiences. Like NY Times interactives, Apple product pages, and award-winning web experiences. Makes websites feel like experiences, not just pages. Use when: scroll animation, parallax, scroll storytelling, interactive story, cinematic website.
anthropic-frontend-design
chaibuilder
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
threejs-postprocessing
CloudAI-X
Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.
snapdom
2025Emma
snapDOM is a fast, accurate DOM-to-image capture tool that converts HTML elements into scalable SVG images. Use for capturing HTML elements, converting DOM to images (SVG, PNG, JPG, WebP), preserving styles, fonts, and pseudo-elements.
keyboard-shortcuts
mae616
UIキーボードショートカットを「公式基準(W3C APG / WCAG)+プラットフォーム規約(Apple HIG / Fluent UI)+デファクトスタンダード(GitHub・Gmail・Slack等)」に沿って設計し、衝突なく・発見しやすく・無効化可能な形で実装するための判断軸。