--- name: webflow-prod-checklist description: "Execute Webflow production deployment checklist \u2014 token security,\ \ rate limit hardening,\nhealth checks, circuit breakers, gradual rollout, and rollback\ \ procedures.\nUse when deploying Webflow integrations to production or preparing\ \ for launch.\nTrigger with phrases like \"webflow production\", \"deploy webflow\"\ ,\n\"webflow go-live\", \"webflow launch checklist\", \"webflow production ready\"\ .\n" allowed-tools: Read, Write, Edit, Bash(curl:*), Bash(npm:*), Grep version: 1.0.0 license: MIT author: Jeremy Longshore tags: - saas - design - no-code - webflow compatibility: Designed for Claude Code --- # Webflow Production Checklist ## Overview Complete pre-deployment checklist for Webflow Data API v2 integrations, covering authentication, error handling, rate limits, monitoring, and rollback. ## Prerequisites - Staging environment tested and verified - Production API token with minimal scopes - Deployment pipeline configured - Monitoring/alerting infrastructure ready ## Instructions ### Pre-Deployment Configuration - [ ] **Production API token** in secure vault (not .env file on server) - [ ] **Minimal scopes** — only scopes the integration actually uses - [ ] **Site token** used where workspace token is not needed - [ ] **Environment variables** set in deployment platform (Vercel/Fly/Cloud Run) - [ ] **Webhook secrets** stored securely, not hardcoded - [ ] **No tokens in client-side code** — all API calls server-side only ### Code Quality Verification - [ ] **All tests passing** — unit tests with mocked SDK, integration tests with test token - [ ] **No hardcoded credentials** — `grep -r "Bearer " src/` returns nothing - [ ] **Error handling** covers 400, 401, 403, 404, 409, 429, 500 - [ ] **Rate limit handling** — SDK `maxRetries` configured, bulk endpoints used - [ ] **Pagination** — all list operations handle `offset`/`limit` correctly - [ ] **Logging** is production-appropriate (no PII, structured JSON) - [ ] **Webhook signatures verified** — `verifyWebhookSignature()` on every webhook ### Rate Limit Readiness - [ ] **Bulk endpoints** used for multi-item operations (100 items/request max) - [ ] **Request queue** with concurrency control (p-queue or similar) - [ ] **Site publish** rate limited to max 1 per minute - [ ] **Retry-After** header honored in custom retry logic - [ ] **SDK maxRetries** set (default: 2, increase for critical paths) ### Health Check Endpoint ```typescript // api/health.ts import { WebflowClient } from "webflow-api"; export async function GET() { const webflow = new WebflowClient({ accessToken: process.env.WEBFLOW_API_TOKEN!, }); const checks: Record = {}; const start = Date.now(); try { const { sites } = await webflow.sites.list(); checks.webflow = { status: "connected", sites: sites?.length || 0, latencyMs: Date.now() - start, }; } catch (error: any) { checks.webflow = { status: "disconnected", error: error.statusCode || error.message, latencyMs: Date.now() - start, }; } const healthy = checks.webflow.status === "connected"; return Response.json( { status: healthy ? "healthy" : "degraded", services: checks, timestamp: new Date().toISOString(), }, { status: healthy ? 200 : 503 } ); } ``` ### Circuit Breaker Pattern ```typescript class WebflowCircuitBreaker { private failures = 0; private lastFailure = 0; private state: "closed" | "open" | "half-open" = "closed"; constructor( private threshold = 5, // failures before opening private resetTimeMs = 60000 // time before trying again ) {} async execute(operation: () => Promise): Promise { if (this.state === "open") { if (Date.now() - this.lastFailure > this.resetTimeMs) { this.state = "half-open"; } else { throw new Error("Circuit breaker is open — Webflow API unavailable"); } } try { const result = await operation(); this.onSuccess(); return result; } catch (error: any) { this.onFailure(); throw error; } } private onSuccess() { this.failures = 0; this.state = "closed"; } private onFailure() { this.failures++; this.lastFailure = Date.now(); if (this.failures >= this.threshold) { this.state = "open"; console.error(`Circuit breaker OPEN after ${this.failures} failures`); } } } const breaker = new WebflowCircuitBreaker(); // Usage const sites = await breaker.execute(() => webflow.sites.list()); ``` ### Monitoring Alerts | Alert | Condition | Severity | |-------|-----------|----------| | API unreachable | Health check fails 3x consecutive | P1 | | Auth failure | Any 401 or 403 response | P1 | | High error rate | Error rate > 5% over 5 min | P2 | | Rate limited | 429 responses > 5/min | P2 | | High latency | P95 > 3000ms | P3 | | Token expiring | Token age > 90 days (rotation schedule) | P3 | ### Graceful Degradation ```typescript async function getContentWithFallback( collectionId: string, cachedData: any[] ): Promise { try { const { items } = await breaker.execute(() => webflow.collections.items.listItemsLive(collectionId) ); // Update cache on success await updateCache(collectionId, items); return items || []; } catch (error) { console.warn("Webflow unavailable, serving cached content"); return cachedData; } } ``` ### Pre-Flight Verification Script ```bash #!/bin/bash echo "=== Webflow Production Pre-Flight ===" # 1. Token works HTTP=$(curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: Bearer $WEBFLOW_API_TOKEN" \ https://api.webflow.com/v2/sites) echo "Token valid: $([ "$HTTP" = "200" ] && echo "YES" || echo "NO (HTTP $HTTP)")" # 2. Webflow platform status STATUS=$(curl -s https://status.webflow.com/api/v2/status.json | \ python3 -c "import sys,json; print(json.load(sys.stdin)['status']['description'])" 2>/dev/null) echo "Webflow status: ${STATUS:-unknown}" # 3. Rate limit headroom curl -s -I -H "Authorization: Bearer $WEBFLOW_API_TOKEN" \ https://api.webflow.com/v2/sites 2>/dev/null | \ grep -i "x-ratelimit-remaining" || echo "Rate limit headers not available" # 4. Health endpoint HEALTH=$(curl -s -o /dev/null -w "%{http_code}" https://your-app.com/api/health) echo "Health endpoint: HTTP $HEALTH" ``` ### Rollback Procedure ```bash # Immediate rollback steps: # 1. Revert to previous deployment vercel rollback # Vercel fly releases # Fly.io — find previous release fly deploy --image registry/app:previous-tag # Fly.io # 2. If using feature flags, disable Webflow integration # 3. Monitor error rates for resolution ``` ## Output - Production-hardened Webflow integration - Health check endpoint with latency tracking - Circuit breaker preventing cascade failures - Monitoring alerts configured - Rollback procedure documented and tested ## Error Handling | Issue | Response | Severity | |-------|----------|----------| | Token revoked in production | Rotate immediately, restart pods | P1 | | Webflow outage | Circuit breaker opens, serve cache | P2 | | Rate limit exhaustion | Queue backs up, requests delayed | P2 | | Webhook delivery failures | Check ngrok/tunnel, verify URL | P3 | ## Resources - [Webflow Status Page](https://status.webflow.com) - [Rate Limits](https://developers.webflow.com/data/reference/rate-limits) - [API Reference](https://developers.webflow.com/data/reference/rest-introduction) ## Next Steps For version upgrades, see `webflow-upgrade-migration`.