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
Code Quality Verification
Rate Limit Readiness
Health Check Endpoint
// 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<string, any> = {};
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
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<T>(operation: () => Promise<T>): Promise<T> {
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
async function getContentWithFallback(
collectionId: string,
cachedData: any[]
): Promise<any[]> {
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
#!/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
# 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
Next Steps
For version upgrades, see webflow-upgrade-migration.
Source: jeremylongshore/claude-code-plugins-plus-skills → plugins/saas-packs/webflow-pack/skills/webflow-prod-checklist/SKILL.md
1---2name: webflow-prod-checklist3description: "\"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\""4allowed-tools: "Read, Write, Edit, Bash(curl:*), Bash(npm:*), Grep"5category: productivity-and-workflow6source_repo: jeremylongshore/claude-code-plugins-plus-skills7source_path: "plugins/saas-packs/webflow-pack/skills/webflow-prod-checklist/SKILL.md"8source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/saas-packs/webflow-pack/skills/webflow-prod-checklist/SKILL.md9---1011# Webflow Production Checklist1213## Overview1415Complete pre-deployment checklist for Webflow Data API v2 integrations, covering16authentication, error handling, rate limits, monitoring, and rollback.1718## Prerequisites1920- Staging environment tested and verified21- Production API token with minimal scopes22- Deployment pipeline configured23- Monitoring/alerting infrastructure ready2425## Instructions2627### Pre-Deployment Configuration2829- [ ] **Production API token** in secure vault (not .env file on server)30- [ ] **Minimal scopes** — only scopes the integration actually uses31- [ ] **Site token** used where workspace token is not needed32- [ ] **Environment variables** set in deployment platform (Vercel/Fly/Cloud Run)33- [ ] **Webhook secrets** stored securely, not hardcoded34- [ ] **No tokens in client-side code** — all API calls server-side only3536### Code Quality Verification3738- [ ] **All tests passing** — unit tests with mocked SDK, integration tests with test token39- [ ] **No hardcoded credentials** — `grep -r "Bearer " src/` returns nothing40- [ ] **Error handling** covers 400, 401, 403, 404, 409, 429, 50041- [ ] **Rate limit handling** — SDK `maxRetries` configured, bulk endpoints used42- [ ] **Pagination** — all list operations handle `offset`/`limit` correctly43- [ ] **Logging** is production-appropriate (no PII, structured JSON)44- [ ] **Webhook signatures verified** — `verifyWebhookSignature()` on every webhook4546### Rate Limit Readiness4748- [ ] **Bulk endpoints** used for multi-item operations (100 items/request max)49- [ ] **Request queue** with concurrency control (p-queue or similar)50- [ ] **Site publish** rate limited to max 1 per minute51- [ ] **Retry-After** header honored in custom retry logic52- [ ] **SDK maxRetries** set (default: 2, increase for critical paths)5354### Health Check Endpoint5556```typescript57// api/health.ts58import { WebflowClient } from "webflow-api";5960export async function GET() {61 const webflow = new WebflowClient({62 accessToken: process.env.WEBFLOW_API_TOKEN!,63 });6465 const checks: Record<string, any> = {};66 const start = Date.now();6768 try {69 const { sites } = await webflow.sites.list();70 checks.webflow = {71 status: "connected",72 sites: sites?.length || 0,73 latencyMs: Date.now() - start,74 };75 } catch (error: any) {76 checks.webflow = {77 status: "disconnected",78 error: error.statusCode || error.message,79 latencyMs: Date.now() - start,80 };81 }8283 const healthy = checks.webflow.status === "connected";8485 return Response.json(86 {87 status: healthy ? "healthy" : "degraded",88 services: checks,89 timestamp: new Date().toISOString(),90 },91 { status: healthy ? 200 : 503 }92 );93}94```9596### Circuit Breaker Pattern9798```typescript99class WebflowCircuitBreaker {100 private failures = 0;101 private lastFailure = 0;102 private state: "closed" | "open" | "half-open" = "closed";103104 constructor(105 private threshold = 5, // failures before opening106 private resetTimeMs = 60000 // time before trying again107 ) {}108109 async execute<T>(operation: () => Promise<T>): Promise<T> {110 if (this.state === "open") {111 if (Date.now() - this.lastFailure > this.resetTimeMs) {112 this.state = "half-open";113 } else {114 throw new Error("Circuit breaker is open — Webflow API unavailable");115 }116 }117118 try {119 const result = await operation();120 this.onSuccess();121 return result;122 } catch (error: any) {123 this.onFailure();124 throw error;125 }126 }127128 private onSuccess() {129 this.failures = 0;130 this.state = "closed";131 }132133 private onFailure() {134 this.failures++;135 this.lastFailure = Date.now();136 if (this.failures >= this.threshold) {137 this.state = "open";138 console.error(`Circuit breaker OPEN after ${this.failures} failures`);139 }140 }141}142143const breaker = new WebflowCircuitBreaker();144145// Usage146const sites = await breaker.execute(() => webflow.sites.list());147```148149### Monitoring Alerts150151| Alert | Condition | Severity |152|-------|-----------|----------|153| API unreachable | Health check fails 3x consecutive | P1 |154| Auth failure | Any 401 or 403 response | P1 |155| High error rate | Error rate > 5% over 5 min | P2 |156| Rate limited | 429 responses > 5/min | P2 |157| High latency | P95 > 3000ms | P3 |158| Token expiring | Token age > 90 days (rotation schedule) | P3 |159160### Graceful Degradation161162```typescript163async function getContentWithFallback(164 collectionId: string,165 cachedData: any[]166): Promise<any[]> {167 try {168 const { items } = await breaker.execute(() =>169 webflow.collections.items.listItemsLive(collectionId)170 );171 // Update cache on success172 await updateCache(collectionId, items);173 return items || [];174 } catch (error) {175 console.warn("Webflow unavailable, serving cached content");176 return cachedData;177 }178}179```180181### Pre-Flight Verification Script182183```bash184#!/bin/bash185echo "=== Webflow Production Pre-Flight ==="186187# 1. Token works188HTTP=$(curl -s -o /dev/null -w "%{http_code}" \189 -H "Authorization: Bearer $WEBFLOW_API_TOKEN" \190 https://api.webflow.com/v2/sites)191echo "Token valid: $([ "$HTTP" = "200" ] && echo "YES" || echo "NO (HTTP $HTTP)")"192193# 2. Webflow platform status194STATUS=$(curl -s https://status.webflow.com/api/v2/status.json | \195 python3 -c "import sys,json; print(json.load(sys.stdin)['status']['description'])" 2>/dev/null)196echo "Webflow status: ${STATUS:-unknown}"197198# 3. Rate limit headroom199curl -s -I -H "Authorization: Bearer $WEBFLOW_API_TOKEN" \200 https://api.webflow.com/v2/sites 2>/dev/null | \201 grep -i "x-ratelimit-remaining" || echo "Rate limit headers not available"202203# 4. Health endpoint204HEALTH=$(curl -s -o /dev/null -w "%{http_code}" https://your-app.com/api/health)205echo "Health endpoint: HTTP $HEALTH"206```207208### Rollback Procedure209210```bash211# Immediate rollback steps:212# 1. Revert to previous deployment213vercel rollback # Vercel214fly releases # Fly.io — find previous release215fly deploy --image registry/app:previous-tag # Fly.io216217# 2. If using feature flags, disable Webflow integration218# 3. Monitor error rates for resolution219```220221## Output222223- Production-hardened Webflow integration224- Health check endpoint with latency tracking225- Circuit breaker preventing cascade failures226- Monitoring alerts configured227- Rollback procedure documented and tested228229## Error Handling230231| Issue | Response | Severity |232|-------|----------|----------|233| Token revoked in production | Rotate immediately, restart pods | P1 |234| Webflow outage | Circuit breaker opens, serve cache | P2 |235| Rate limit exhaustion | Queue backs up, requests delayed | P2 |236| Webhook delivery failures | Check ngrok/tunnel, verify URL | P3 |237238## Resources239240- [Webflow Status Page](https://status.webflow.com)241- [Rate Limits](https://developers.webflow.com/data/reference/rate-limits)242- [API Reference](https://developers.webflow.com/data/reference/rest-introduction)243244## Next Steps245246For version upgrades, see `webflow-upgrade-migration`.247248---249250**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/saas-packs/webflow-pack/skills/webflow-prod-checklist/SKILL.md`