| name | canva-local-dev-loop |
| description | Configure Canva Connect API local development with hot reload and mock server.
Use when setting up a development environment, testing OAuth flows locally,
or establishing a fast iteration cycle for Canva integrations.
Trigger with phrases like "canva dev setup", "canva local development",
"canva dev environment", "develop with canva", "canva mock".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep |
| version | 1.5.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
| tags | ["saas","design","canva"] |
| compatibility | Designed for Claude Code |
Canva Local Dev Loop
Overview
Set up a fast local development environment for Canva Connect API integrations with a token management server, mock API for testing, and hot reload.
Prerequisites
- Completed
canva-install-auth setup
- Node.js 18+ with npm/pnpm
- ngrok or similar tunnel for OAuth callbacks (or use localhost with Canva dev settings)
Instructions
Step 1: Project Structure
my-canva-app/
โโโ src/
โ โโโ canva/
โ โ โโโ client.ts # REST client wrapper (from canva-sdk-patterns)
โ โ โโโ auth.ts # OAuth PKCE flow
โ โ โโโ types.ts # API response types
โ โโโ routes/
โ โ โโโ auth.ts # OAuth callback handler
โ โ โโโ designs.ts # Design CRUD routes
โ โโโ index.ts
โโโ tests/
โ โโโ canva-mock.ts # Mock Canva API server
โ โโโ designs.test.ts
โโโ .env.local # Local secrets (git-ignored)
โโโ .env.example # Template for team
โโโ package.json
โโโ tsconfig.json
Step 2: Environment Setup
CANVA_CLIENT_ID=
CANVA_CLIENT_SECRET=
CANVA_REDIRECT_URI=http://localhost:3000/auth/canva/callback
PORT=3000
cp .env.example .env.local
Step 3: OAuth Callback Server
import express from 'express';
import { generatePKCE, getAuthorizationUrl, exchangeCodeForToken } from '../canva/auth';
const router = express.Router();
const pkceStore = new Map<string, string>();
router.get('/auth/canva/start', (req, res) => {
const { verifier, challenge } = generatePKCE();
const state = crypto.();
pkceStore.(state, verifier);
url = ({
: process..!,
: process..!,
: [, , , ],
: challenge,
state,
});
res.(url);
});
router.(, (req, res) => {
{ code, state } = req. { : ; : };
verifier = pkceStore.(state);
(!verifier) res.().();
pkceStore.(state);
tokens = ({
code,
: verifier,
: process..!,
: process..!,
: process..!,
});
.(, tokens., );
res.();
});