Configure Miro local development with hot reload, testing, and ngrok tunneling.
Use when setting up a development environment, configuring test workflows,
or establishing a fast iteration cycle with the Miro REST API v2.
Trigger with phrases like "miro dev setup", "miro local development",
"miro dev environment", "develop with miro", "miro testing".
Configure Miro local development with hot reload, testing, and ngrok tunneling.
Use when setting up a development environment, configuring test workflows,
or establishing a fast iteration cycle with the Miro REST API v2.
Trigger with phrases like "miro dev setup", "miro local development",
"miro dev environment", "develop with miro", "miro testing".
allowed-tools
Read, Write, Edit, Bash(npm:*), Bash(npx:*), Grep
version
1.7.0
license
MIT
author
Jeremy Longshore <jeremy@intentsolutions.io>
tags
["saas","miro","development","testing"]
compatibility
Designed for Claude Code
Miro Local Dev Loop
Overview
Set up a fast local development workflow for building Miro integrations, including hot reload, test mocking against the REST API v2, and ngrok tunneling for webhooks.
Prerequisites
Completed miro-install-auth setup
Node.js 18+ with npm or pnpm
Access token with boards:read and boards:write scopes
{"scripts":{"dev":"tsx watch src/index.ts","test":"vitest","test:watch":"vitest --watch","test:integration":"MIRO_TEST_MODE=live vitest run tests/integration/","tunnel":"ngrok http 3000","typecheck":"tsc --noEmit"},
"dependencies"
:
{
"@mirohq/miro-api"
:
"^2.0.0"
,
"express"
:
"^4.18.0"
,
"dotenv"
:
"^16.0.0"
}
,
"devDependencies"
:
{
"tsx"
:
"^4.0.0"
,
"vitest"
:
"^1.0.0"
,
"typescript"
:
"^5.0.0"
}
}
Step 3: Miro Client Singleton
// src/miro/client.tsimport { MiroApi } from'@mirohq/miro-api';
letinstance: MiroApi | null = null;
exportfunctiongetMiroApi(): MiroApi {
if (!instance) {
const token = process.env.MIRO_ACCESS_TOKEN;
if (!token) thrownewError('MIRO_ACCESS_TOKEN not set');
instance = newMiroApi(token);
}
return instance;
}
// For testing — allow injecting a mockexportfunctionresetMiroApi(): void {
instance = null;
}
Step 4: Test Fixtures from Real API Responses
// tests/fixtures/board.json{"id":"uXjVN1234567890","type":"board","name":"Test Board","description":"Fixture for unit tests","createdAt":"2025-01-15T10:00:00Z","modifiedAt":"2025-01-15T10:30:00Z","owner":{"id":"123456","type":"user","name":"Dev User"},"policy":{"sharingPolicy":{"access":"private"},"permissionsPolicy":{"collaborationToolsStartAccess":"all_editors"}}}
# Start your dev server
npm run dev
# In another terminal, start ngrok
ngrok http 3000
# Copy the HTTPS URL (e.g., https://abc123.ngrok.app)# Register it as a webhook callback in your Miro app settings# or via the API (see miro-webhooks-events skill)
Step 7: Debug Logging
// Enable verbose HTTP logging during developmentimport { MiroApi } from'@mirohq/miro-api';
// Log all API requests and responsesconst api = newMiroApi(process.env.MIRO_ACCESS_TOKEN!, {
logger: {
info: (...args) =>console.log('[MIRO]', ...args),
warn: (...args) =>console.warn('[MIRO]', ...args),
error: (...args) =>console.error('[MIRO]', ...args),
},
});
Environment Variables
Variable
Required
Description
MIRO_ACCESS_TOKEN
Yes
OAuth 2.0 access token
MIRO_CLIENT_ID
For OAuth flow
App client ID
MIRO_CLIENT_SECRET
For OAuth flow
App client secret
MIRO_REDIRECT_URI
For OAuth flow
OAuth callback URL
MIRO_TEST_BOARD_ID
For integration tests
Board ID for live tests
Output
Following this guide produces the Miro integration outcome for its topic—configuration, validation evidence, operational recovery, or a documented migration result. Record command output and relevant identifiers so a failed step is traceable.
Examples
Start with the smallest applicable command or code example in the relevant section, using a dedicated test board and non-production credentials. Confirm the expected response or validation result before applying the pattern to production.