Skip to main content
miro-deploy-integration Deploy Miro REST API v2 integrations to Vercel, Fly.io, and Cloud Run
with proper OAuth token management and webhook configuration.
Trigger with phrases like "deploy miro", "miro Vercel",
"miro production deploy", "miro Cloud Run", "miro Fly.io".
Aller à l'installation Skills Marketplace Découvrez et explorez les compétences IA créées par la communauté.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Copier le promptAfficher les détails du prompt Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/jeremylongshore/claude-code-plugins-plus-skills --skill miro-deploy-integrationLa commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Télécharger Zip Téléchargement... Métiers associés SOC
Basé sur la classification professionnelle SOC
name miro-deploy-integration description Deploy Miro REST API v2 integrations to Vercel, Fly.io, and Cloud Run
with proper OAuth token management and webhook configuration.
Trigger with phrases like "deploy miro", "miro Vercel",
"miro production deploy", "miro Cloud Run", "miro Fly.io".
allowed-tools Read, Write, Edit, Bash(vercel:*), Bash(fly:*), Bash(gcloud:*) version 1.6.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","miro","deployment","cloud"] compatibility Designed for Claude Code
Miro Deploy Integration
Overview
Deploy Miro REST API v2 integrations to popular platforms with proper OAuth 2.0 token management, webhook endpoint setup, and health monitoring.
Prerequisites
Miro app configured with production OAuth credentials
Access token with required scopes
Platform CLI installed (vercel, fly, or gcloud)
Vercel Deployment
Environment Variables
vercel env add MIRO_CLIENT_ID production
vercel env add MIRO_CLIENT_SECRET production
vercel env add MIRO_ACCESS_TOKEN production
vercel env add MIRO_WEBHOOK_SECRET production
API Route: Webhook Handler
import crypto from 'crypto' ;
export const config = { api : { bodyParser : false } };
export default async function handler (req, res ) {
if (req.method !== 'POST' ) return res.status (405 ).end ();
const chunks : Buffer [] = [];
for await (const chunk of req) chunks.push (chunk);
const rawBody = Buffer .concat (chunks);
signature = req. [ ] ;
expected = crypto. ( , process. . !)
. (rawBody). ( );
(!signature || !crypto. ( . (signature), . (expected))) {
res. ( ). ({ : });
}
event = . (rawBody. ());
(event. ) {
:
. ( );
;
}
res. ( ). ({ : });
}
const
headers
'x-miro-signature'
as
string
const
createHmac
'sha256'
env
MIRO_WEBHOOK_SECRET
update
digest
'hex'
if
timingSafeEqual
Buffer
from
Buffer
from
return
status
401
json
error
'Invalid signature'
const
JSON
parse
toString
switch
event
case
'board_subscription_changed'
console
log
`Board ${event.boardId} : item ${event.item?.type } ${event.type } `
break
status
200
json
received
true
API Route: OAuth Callback
export default async function handler (req, res ) {
const { code } = req.query ;
const tokenResponse = await fetch ('https://api.miro.com/v1/oauth/token' , {
method : 'POST' ,
headers : { 'Content-Type' : 'application/x-www-form-urlencoded' },
body : new URLSearchParams ({
grant_type : 'authorization_code' ,
client_id : process.env .MIRO_CLIENT_ID !,
client_secret : process.env .MIRO_CLIENT_SECRET !,
code : code as string ,
redirect_uri : `${process.env.VERCEL_URL} /api/auth/miro/callback` ,
}),
});
const tokens = await tokenResponse.json ();
res.redirect ('/dashboard?connected=miro' );
}
vercel.json {
"functions" : {
"api/webhooks/miro.ts" : { "maxDuration" : 10 } ,
"api/auth/miro/callback.ts" : { "maxDuration" : 10 }
} ,
"headers" : [
{
"source" : "/api/health" ,
"headers" : [ { "key" : "Cache-Control" , "value" : "no-store" } ]
}
]
}
Fly.io Deployment
fly.toml app = "my-miro-integration"
primary_region = "iad"
[env]
NODE_ENV = "production"
MIRO_API_BASE = "https://api.miro.com/v2"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = "suspend"
auto_start_machines = true
min_machines_running = 1
[[http_service.checks]]
grace_period = "10s"
interval = "30s"
method = "GET"
path = "/health"
timeout = "5s"
Deploy
fly secrets set MIRO_CLIENT_ID=your_client_id
fly secrets set MIRO_CLIENT_SECRET=your_client_secret
fly secrets set MIRO_ACCESS_TOKEN=your_token
fly secrets set MIRO_WEBHOOK_SECRET=your_webhook_secret
fly deploy
fly ssh console -C "curl -s http://localhost:3000/health | jq '.miro'"
Google Cloud Run
Deploy Script #!/bin/bash
set -euo pipefail
PROJECT_ID="${GOOGLE_CLOUD_PROJECT} "
SERVICE_NAME="miro-integration"
REGION="us-central1"
echo -n "$MIRO_CLIENT_SECRET " | gcloud secrets create miro-client-secret --data-file=-
echo -n "$MIRO_ACCESS_TOKEN " | gcloud secrets create miro-access-token --data-file=-
echo -n "$MIRO_WEBHOOK_SECRET " | gcloud secrets create miro-webhook-secret --data-file=-
gcloud run deploy $SERVICE_NAME \
--source . \
--region $REGION \
--platform managed \
--allow-unauthenticated \
--min-instances 1 \
--set-env-vars "MIRO_CLIENT_ID=$MIRO_CLIENT_ID ,MIRO_API_BASE=https://api.miro.com/v2" \
--set-secrets "MIRO_CLIENT_SECRET=miro-client-secret:latest,MIRO_ACCESS_TOKEN=miro-access-token:latest,MIRO_WEBHOOK_SECRET=miro-webhook-secret:latest"
Health Check Endpoint
export async function healthCheck ( ): Promise <HealthResponse > {
const checks : Record <string , unknown > = {};
const start = Date .now ();
try {
const response = await fetch ('https://api.miro.com/v2/boards?limit=1' , {
headers : { 'Authorization' : `Bearer ${process.env.MIRO_ACCESS_TOKEN} ` },
signal : AbortSignal .timeout (5000 ),
});
checks.miro = {
status : response.ok ? 'healthy' : 'degraded' ,
latencyMs : Date .now () - start,
rateLimitRemaining : response.headers .get ('X-RateLimit-Remaining' ),
httpStatus : response.status ,
};
} catch (err) {
checks.miro = { status : 'unhealthy' , error : err.message };
}
return {
status : Object .values (checks).every ((c : any ) => c.status === 'healthy' ) ? 'healthy' : 'degraded' ,
services : checks,
timestamp : new Date ().toISOString (),
};
}
Webhook URL Registration via API After deploying, register your webhook endpoint programmatically:
const subscription = await fetch (
'https://api.miro.com/v2-experimental/webhooks/board_subscriptions' ,
{
method : 'POST' ,
headers : {
'Authorization' : `Bearer ${process.env.MIRO_ACCESS_TOKEN} ` ,
'Content-Type' : 'application/json' ,
},
body : JSON .stringify ({
boardId : 'your-board-id' ,
callbackUrl : 'https://your-app.com/api/webhooks/miro' ,
status : 'enabled' ,
}),
}
);
Error Handling Issue Cause Solution Webhook delivery fails URL not HTTPS Ensure force_https is enabled Token expires in production No refresh logic Implement scheduled token refresh Cold start misses webhook Min instances = 0 Set min_machines_running = 1 Secret rotation breaks deploy Old secret cached Restart service after secret update
Resources
Next Steps For webhook handling patterns, see miro-webhooks-events.