Skip to main content

Your first Bangle Editor

To get started with your first Bangle Editor let us buld an editor which supports bold and headings.


There is a lot going on in the above example, so lets distill it down into smaller parts:

  • Components: heading, bold
  • specs: heading.spec(), bold.spec()
  • plugins: heading.plugins(), bold.plugins()
  • initialValue: Hello world!

Bangle component#

A component is an object which hold smaller related things to form the building block of your editor. Let us look at high level overview of the bold component:

export const bold = {    spec(opts) {        type: 'mark',        name: 'bold',        schema: {            ...        },        markdown: {            ...        }    },    plugins(opts) {        return [ ... ]    },    commands: {        toggleBold: () => { .... },        ...    }}


Short for specification, is an object that declaratively defines how your editor behaves, looks, its relationship with other entities and the parsing/serialization aspect of it. You can either create a SpecRegistry instance yourself or pass an array of specs and let Bangle create it for you internally.

const specs = [bold.spec()];const state1 = new BangleEditorState({    specRegistry: new SpecRegistry(specs),    ...});const state2 = new BangleEditorState({    specs: specs    ...});// state1 and state2 are essentially different// ways to do the same thing

💡 The specs: [...] style should fit majority of use cases. The new SpecRegistry syntax comes in handy when dealing with multiple syncronized editors which need to rely on a single instance of specRegistry or if your application needs access to {{core.links.Prosemirror.Schema}}.

You might have noticed that we are using an array to order the specs. For most use cases the order doesn't matter, however if two or more specs are competing, for example, a link spec vs bold spec, putting link spec before bold ensures that your output will look like <bold>will wrap <a href="hola">a link tag</a>.

📖 Handy links:


Plugins allow you to add interactivity to your editor. They allow for things like keyboard shortcuts, drag-n-drop, paste, etc.

💡 Not every component has .plugin(), as some components are pretty simple, check the API doc of each component before using.

💡 There is no explicit connection between a component's plugins and spec, so feel free to mix, match them or even replace them with your own.

📖 Creating a custom component is a slightly complex topic, as you can pretty much do anything with plugins. Only dig deeper into plugin API if you want to build your own plugins, here are some handy links:


Bangle accepts variety of things as initial value.

  • You can use a vanilla string:
new BangleEditorState({  initialValue: `Hello world`,});
new BangleEditorState({  initialValue: `<div><p>Hello world</p></div>`,});
new BangleEditorState({  initialValue: {    type: 'doc',    content: [      {        type: 'paragraph',        content: [          {            type: 'text',            text: 'Hello world',          },        ],      },    ],  },});