Skillshub canva-deploy-integration
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/canva-deploy-integration" ~/.claude/skills/comeonoliver-skillshub-canva-deploy-integration && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/canva-deploy-integration/SKILL.mdsource content
Canva Deploy Integration
Overview
Deploy Canva Connect API integrations to popular platforms with secure OAuth credential management. The Canva API requires server-side token exchange — client secrets and refresh tokens must never reach the browser.
Prerequisites
- Canva OAuth credentials (client ID + secret)
- Platform CLI installed (vercel, fly, or gcloud)
- HTTPS domain for OAuth redirect URIs
- Application code ready for deployment
Vercel
Secrets
# Add Canva OAuth credentials vercel env add CANVA_CLIENT_ID production vercel env add CANVA_CLIENT_SECRET production vercel env add CANVA_REDIRECT_URI production # e.g. https://your-app.vercel.app/auth/canva/callback
vercel.json
{ "functions": { "api/**/*.ts": { "maxDuration": 30 } }, "headers": [ { "source": "/api/(.*)", "headers": [ { "key": "Cache-Control", "value": "no-store" } ] } ] }
API Route (Next.js / Vercel Functions)
// api/canva/callback.ts — OAuth callback export async function GET(req: Request) { const url = new URL(req.url); const code = url.searchParams.get('code'); const state = url.searchParams.get('state'); // Exchange code for tokens (server-side only) const tokens = await exchangeCodeForToken({ code: code!, codeVerifier: await getVerifierFromSession(state!), clientId: process.env.CANVA_CLIENT_ID!, clientSecret: process.env.CANVA_CLIENT_SECRET!, redirectUri: process.env.CANVA_REDIRECT_URI!, }); // Store tokens in your database await saveTokens(userId, tokens); return Response.redirect('/dashboard'); }
Fly.io
fly.toml
app = "my-canva-app" primary_region = "iad" [env] NODE_ENV = "production" CANVA_REDIRECT_URI = "https://my-canva-app.fly.dev/auth/canva/callback" [http_service] internal_port = 3000 force_https = true auto_stop_machines = true auto_start_machines = true
Secrets
fly secrets set CANVA_CLIENT_ID=OCAxxxxxxxxxxxxxxxx fly secrets set CANVA_CLIENT_SECRET=xxxxxxxxxxxxxxxx fly deploy
Google Cloud Run
Deploy Script
#!/bin/bash PROJECT_ID="${GOOGLE_CLOUD_PROJECT}" SERVICE_NAME="canva-integration" REGION="us-central1" # Store secrets in Secret Manager echo -n "OCAxxxxxxxxxxxxxxxx" | gcloud secrets create canva-client-id --data-file=- echo -n "xxxxxxxxxxxxxxxx" | gcloud secrets create canva-client-secret --data-file=- # Build and deploy gcloud builds submit --tag gcr.io/$PROJECT_ID/$SERVICE_NAME gcloud run deploy $SERVICE_NAME \ --image gcr.io/$PROJECT_ID/$SERVICE_NAME \ --region $REGION \ --platform managed \ --allow-unauthenticated \ --set-secrets="CANVA_CLIENT_ID=canva-client-id:latest,CANVA_CLIENT_SECRET=canva-client-secret:latest" \ --set-env-vars="CANVA_REDIRECT_URI=https://$SERVICE_NAME-xxxxx.run.app/auth/canva/callback"
Health Check
// api/health.ts — confirms Canva API connectivity export async function GET() { const start = Date.now(); let canvaStatus: string; try { const res = await fetch('https://api.canva.com/rest/v1/users/me', { headers: { 'Authorization': `Bearer ${await getServiceToken()}` }, signal: AbortSignal.timeout(5000), }); canvaStatus = res.ok ? 'healthy' : `error:${res.status}`; } catch { canvaStatus = 'unreachable'; } return Response.json({ status: canvaStatus === 'healthy' ? 'healthy' : 'degraded', services: { canva: { status: canvaStatus, latencyMs: Date.now() - start } }, timestamp: new Date().toISOString(), }); }
Redirect URI Configuration
After deploying, update your Canva integration settings with the production redirect URI:
| Platform | Redirect URI Pattern |
|---|---|
| Vercel | |
| Fly.io | |
| Cloud Run | |
| Custom Domain | |
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| OAuth callback fails | Redirect URI mismatch | Update URI in Canva dashboard |
| Secret not found | Missing env var | Add via platform CLI |
| Cold start timeout | OAuth exchange slow | Set min instances to 1 |
| HTTPS required | HTTP redirect URI | All platforms default to HTTPS |
Resources
Next Steps
For webhook handling, see
canva-webhooks-events.