A Miro app for event modeling. It uses the Web SDK v2 with React and TypeScript. The toolbar icon opens a panel with four tabs. Each element that the app places is a native, editable Miro widget. The user guide gives the full description.
Build — the modeling palette. Drag a tile onto the board, or click a tile to place the element at the center of the view. The colored tiles are the typed blocks: Event, Command, Read model, External event, Error, Note, Automation, and Screen. The fill color of a sticky gives its type. Below the blocks are the tool tiles: Slice (a frame that holds one atomic feature), Specification (a Given/When/Then frame whose + buttons bring in linked copies of blocks from the model), Swimlane, and Chapter. The tab also has the pattern stamps, which need one click, and the Convert tools. To link blocks, use the connector tool of Miro.
Properties — rename the selected block, and give named, typed fields to
the blocks that carry data. A sticky shows its fields in its own text. A screen
or an automation shows its fields in a box below it. Each field is one line of
board notation. The buttons add the parts of the notation: [] (collection),
! (generated), ? (optional), → (fed by an upstream field, an alias), and
= (an example). In the image, the name field of an Event is fed by an
upstream full_name field, and has the example Alex.
Select one attached connector and the same tab becomes the arrow toolset. Copy merges fields across the link. Replace writes over them. Navigate to moves the view to either end.
Generate (beta) — paste a description of a system or a workflow, or import a Figma file or exported design PDF files. Claude then drafts a full model: typed blocks in three lanes, connectors, slices, and Given/When/Then specifications. The app keeps your Anthropic API key in this browser only. It never writes the key to the board. Select a model and, if you want, edit the first part of the system prompt.
Beta. A model that the AI drafts is a start point to improve, not a finished model. The accuracy changes with the source, and a large design can be larger than the storage of one board.
Console (no image) — a log of each failure that the app finds. The log continues to record with the panel closed. The tab also shows a meter of the Miro API credits that the app spent in the last minute and the last hour.
A background pass makes an arrow red if it points into a block whose incoming
blocks do not supply all of the required fields of that block. It also puts the
missing fields in the caption of the arrow. In the image below, the
Register user command does not supply the timestamp that User registered
requires. The arrow is thus red, and its caption is timestamp : datetime. The
generated field id : UUID! is not included, because no upstream block must
supply it.
A Miro app is a small web app that Miro loads in a board:
| File | Role |
|---|---|
index.html |
The App URL. It loads on the board, stays invisible, and registers the toolbar icon. |
app.html |
It holds the React panel. React mounts into its #root element. |
src/index.ts |
The composition root of the headless board script. It connects the Miro adapters, the icon-click flow, the selection flow, and the background housekeeping passes. |
src/app.tsx |
The composition root of the panel. It connects the adapters, which include the Anthropic planner, and mounts the React panel. |
src/domain/* |
Pure event-modeling logic with no platform code: vocabulary, fields, specifications, completeness, the generator plan, and more. It never uses miro. |
src/ports/* |
The interfaces that the use-cases speak to: Canvas, store, notifier, viewport, planner, and more. |
src/services.ts |
The service locator. It is the one place where a feature obtains its ports. |
src/features/* |
The use-cases, one module for each feature: stickies, screens, slices, specifications, fields, generate, and more. They speak only to ports. |
src/adapters/* |
The only place where platform SDKs appear: miro/ (the Web SDK), anthropic/ (the AI planner, panel only), and browser/ (diagnostics and the credit meter). |
src/panel/* |
The React components: the Panel with four tabs and its section components. Each component has its CSS file in the same directory. |
vite.config.ts |
The React plugin, the dev server on port 3000, and the two HTML pages as build inputs. |
tsconfig.json |
The TypeScript configuration (strict, react-jsx, and the Miro SDK global types). |
The src/ tree is a hexagonal (ports-and-adapters) architecture. The domain
and the features never import miro. Thus you can move the event-modeling logic
to a different canvas if you replace the set of adapters. The miro global gets
its types from
@mirohq/websdk-types,
through the types field of tsconfig.json. No import is necessary.
- Node.js 20.19+ / 22.12+ / 24+ and npm (Vite 8 needs these versions)
- A Miro account with a Developer team. It is free, and Miro makes it when you make your first app.
npm install
npm run startThis serves the app at http://localhost:3000. Let it continue to run.
Other scripts: npm run typecheck (runs tsc), npm run build (typecheck plus
production build), and npm run preview (serves the build).
- Go to https://miro.com/app/settings/user-profile/apps (Profile settings → Your apps) and click Create new app.
- Give the app a name, for example
Event Modeler. Select your Developer team. Then create the app. - On the app settings page:
- In App URL, enter
http://localhost:3000. Miro permitshttpforlocalhostduring development. - In Permissions / Scopes, enable
boards:readandboards:write. - (Optional) Upload an app icon.
- In App URL, enter
- Click Install app and get OAuth token, select your Developer team, and confirm.
- Open or create a board in that Developer team.
- In the left toolbar, open the Apps menu (the "+" or "More apps" icon) and select your app. Miro adds its icon to the toolbar.
- Click the icon. The panel opens. Then drag a building block onto the board. 🎉
npm run build # typecheck, then write the static files to dist/
npm run preview # serve the production build locallyDeploy dist/ to any static host, for example Vercel, Netlify, or GitHub Pages.
Then change the App URL in your Miro app settings to the deployed HTTPS URL.




