Quick Start
This walkthrough builds the smallest useful setup: one block, two modes, a toolbox, and a workspace — with a runtime mode switch at the end.
-
Define your blocks in a definitions JSON. A block declares named elements (its visual parts); the global
elementTypesregistry says what each element name is; modes pick which elements are shown.definitions.json {"elementTypes": {"title": "text","conceptual": "code","python": "code"},"modes": [{ "name": "conceptual", "elements": ["title", "conceptual"] },{ "name": "python", "elements": ["title", "python"] }],"categories": [{ "name": "Output", "color": "#5C81A6" }],"blocks": [{"identifier": "text_print","category": "Output","elements": {"title": "Print","conceptual": "Output %1","python": "print(%1)"},"inputSlots": {"1": { "kind": "value", "name": "TEXT" }}}]}%1is an input slot — it becomes a Blockly input on the block and a substitution point in text renderings. -
Write a behavior for the block. Behaviors generate the executable JavaScript, one function per block identifier:
behaviors.ts import type { MorphicBehaviorMap } from "morphic-blocks";export const behaviors: MorphicBehaviorMap = {text_print(proxy) {return `console.log(${proxy.inputs.TEXT ?? "undefined"});\n`;},}; -
Add containers to your page:
<div id="toolbox"></div><div id="workspace"></div> -
Mount the engine:
main.ts import { MorphicBlocks } from "morphic-blocks";import definitions from "./definitions.json";import { behaviors } from "./behaviors";// The constructor takes the whole definitions file plus your behaviors.// mount() and mountToolbox() inherit its modes / presets / highlighting /// categories, so a call only carries runtime concerns.const engine = new MorphicBlocks(definitions, behaviors);engine.mount({workspaceContainer: document.getElementById("workspace")!,workspaceMode: "conceptual",toolboxMode: "conceptual",});engine.mountToolbox(document.getElementById("toolbox")!);Drag the Print tile from the toolbox into the workspace — it creates a real Blockly block.
-
Switch modes at runtime. The same blocks re-render with the
pythonelement as their template:engine.setModes({ workspaceMode: "python", toolboxMode: "python" }); -
Generate code from the workspace via your behaviors:
const js = engine.generateJavaScript();
Where to go from here
Section titled “Where to go from here”- Blocks & Elements — the model behind what you just wrote.
- Presets & Views — name mode combinations and drive whole layouts.
- The Definitions Format — every field, explained.
- Style your modes with CSS — see Styling Modes.