How to extend bpmn-io with custom elements?


for my master thesis I’d like to implement a modeling tool based on bpmn-io (the offline version). Therefore I have to extend the modeler (palette) with new elements.

I have already downloaded bpmn-io-chrome and it is running with a local version of bpmn-js. In that local bpmn-js, I have added a new element to the PaletteProvider and also added this new element to the BpmnRenderer.
The result so far is the following: The new element does show up with its icon in the palette but I can not create an element by dragging the icon to the workspace, I can just drag the icon around, but no “real” shape is created.

Do you have any suggestions what I am missing? What is the correct way to add a new element to the modeler?

Thanks for any help!

Best regards,


We created a custom elements guide that should get you covered.

See also bpmn-js-nyan for more fun.

Hi, i have the same question, if you have some answers please let met know


Basically the renderer needs to know how to draw your custom element. This will make sure it is drawn as a preview during create. I assume you added it via PaletteProvider#createAction?

Feel free to put your current work in progress up somewhere so we can have a look into it. Just based on your description it is not possible for us to track what is wrong.

Thanks for the fast reply!

Yes, I have added the new element to the list of actions (see here) and implemented a draw method in the renderer (see here) and added the element to the handlers (see line 344 in the second link).

Did you had the chance to have a look at my code and do have any clue what is missing to make the new element work?

Thanks and best regards,

Hi Kerstin,

there are some errors in your code, which are preventing bpmn-js to work properly: There is an obsolete group statement here and a missing + at the end of the line here.

In general it’s a good practice to run the test suite first. If all tests are passing, everything should be working fine. If not it gives you hints, why your changes in the code are not working. You can run the test suite on your command line by running grunt inside the bpmn-js folder like this: grunt auto-test
Then grunt listens for changes in the code and the test suite is getting restarted on every change.

You can also find syntax errors like the ones mentioned above, if you’re just running grunt (without arguments), which checks syntax errors via JSHint.

Thanks for the hint with the test suite!
If I run grunt auto-test in the original bpmn-js folder (without any changes), I’ll get 35 errors (e.g. PhantomJS 1.9.8 (Linux 0.0.0) modeling/behavior - drop on connection execution should connect start -> target -> end FAILED).
Does anyone get such errors when running grunt in the original bpmn-js folder?

Hey @Kerstin,

did you run grunt task ? Because this task acts as a general development protocol, which checks the project’s files for syntax errors, runs the test suite and generates documentation.

If you cloned our project from the master branch, the test suite should pass without any failing test cases.


@Kerstin, are you also using a local diagram-js ?


Do I need a local diagram-js?
After I have cloned the master branch of bpmn-js, I’ve run npm install and then grunt. Then I get the error that the modules ‘diagram-js/lib/features/label-support’, ‘diagram-js/lib/features/attach-support’ and ‘diagram-js/lib/util/LineIntersection’ were not found.
When I have installed bpmn-js via npm install --save bpmn-js, only LineIntersection was missing. I have added that file manually from the github repo and run grunt. Then I’ve got these 35 errors.

I am experiencing a very similiar problem than the one described in this thread initially. I am modifying the bpmn-js so it shows a custom item in the palette. However when I click on it, it does create a real shape. I even tried what was suggested here but I keep getting a javascript error "Uncaught Error: unknown type ". Can someone tell me if I am missing something?

Try to debug the code to gain additional understanding of where the error originates.

From the demand for adding custom elements we should probably add an example how to add custom elements in the near future.

1 Like

Could you guys give me some input on your custom element use cases? It helps us building an example that is actually useful for you.

(a) When do the additional elements get created? (during import, post import, via user interaction)
(b) How are the custom elements getting persisted? (in BPMN 2.0 XML, server side, other file)

In my use case the palette should be extended with other elements (and some of the existing ones should be removed). The user only creates a model with these elements. There will be no imports. The model should be stored in an XML file for further processing.

(a) via user interaction
(b) XML file

Thank you for building an example!

@Kerstin Based on your feedback I got two additional questions:

  • After saving the diagram, the BPMN 2.0 XML contains the custom elements?
  • Given that is true, what should happen if the user reopens the diagram with existing custom elements?

The underlying issue I would like to clarify, if or how the custom elements should reside in the BPMN 2.0 document. If they should be stored in the document, they must be attached in a BPMN compliant manner. If they should be stored externally these overlays or however you call them can be added separately and have to be saved separately, too.

The custom elements can be stored in a separate XML file and do not have to be BPMN compliant.

We added a custom elements example.

Thanks a lot!

Just two more questions:

  1. How can I connect custom elements? (a custom element must only be connected to another custom element)
  2. Is there a chance to store the custom elements and their connections in a XML file? (can be included in the BPMN file or in another separated one)

Allow custom connections to be created, create a new context pad entry for custom elements and make sure to override modeling.connect() to create the correct connection type.

It is up to you, where you store the custom elements. In the example we choose JSON, simply because it is dead easy to implement. If you would like to have your custom XML datastucture or hijack the <bpmn:documentation /> tag to inline custom elements into the BPMN 2.0 XML, go ahead. We do the latter in the bpmn-js commenting example.

Is there a way to extend the ContextPadProvider in my own application or do I have to change the bpmn-js code?
I have tried to include a CustomContextPadProvider with the entries for the custom elements, but it does not work. Here is the index.js of my application:

window.jQuery = require(‘jquery’);

var angular = require(‘angular’);

var ngModule = module.exports = angular.module(‘app’, [

var CustomModeler = require(’./custom-modeler’);

var overrideModule = {
contextPadProvider: [ ‘type’, require(’./custom-modeler/custom/CustomContextPadProvider’) ]

var modeler = new CustomModeler({ container: ‘#canvas’, keyboard: { bindTo: document }, additionalModules: [ overrideModule ]});

window.bpmnjs = modeler;