Scaffold a plugin, run the dev server, and see it working in the editor in under ten minutes
This guide builds a minimal counter plugin — a button that increments a number. It is simple enough to complete in under ten minutes and demonstrates the core SDK concepts you will use in every plugin.
The scaffolding tool creates this structure:
Open manifest.json. It describes your plugin to the registry and to the Chalk parser:
The chalk.element field is the name educators use in Chalk. The chalk.attributes field declares what attributes the element accepts and their types — the Chalk parser validates against this.
Open src/main.js:
Three things to notice:
onInitialize receives your resolved attrs — attrs.start is the number the educator wrote in Chalkinternote.ready() is called after the first render is painted — the host shows a loading state until this firesonUnload is where you cancel animation loops, disconnect observers, and release resourcesThe dev server starts on port 4444 by default. You will see:
Because Internote is a web application, there is no local internote runtime to run against — the editor itself is your testing environment. The dev CLI bridges the gap: npm run dev registers your local plugin with the editor so it appears as a loadable plugin in your account during development.
Open a new internote in the editor. The CLI prints a local plugin identifier you use as the src in your @plugin directive:
The editor reads the manifest from the file path, registers the counter element, validates the attrs, and renders the plugin iframe. You should see your button.
File path plugin sources only work in the editor while the dev CLI is running and only for your account. They are not valid in published internotes — replace with the registry URL before sharing.
The plugin runs in a sandboxed iframe. To open DevTools for the plugin frame specifically, right-click inside the plugin element in the editor and choose Inspect Plugin Frame. This opens a DevTools panel scoped to the sandbox — you can use the console, set breakpoints in your plugin code, and inspect the DOM the plugin has rendered.
The editor also shows a plugin error state with the message when your plugin calls internote.error() or throws an uncaught exception, so you do not need DevTools open to catch crashes during normal testing.
Edit src/main.js — add a Reset button. The dev server watches for changes; refresh the editor to pick them up.
You now have a working plugin loading in the editor. Read the pages below to learn each SDK capability in depth.