From framer-pack
Implement Framer rate limiting, backoff, and idempotency patterns. Use when handling rate limit errors, implementing retry logic, or optimizing API request throughput for Framer. Trigger with phrases like "framer rate limit", "framer throttling", "framer 429", "framer retry", "framer backoff".
npx claudepluginhub flight505/skill-forge --plugin framer-packThis skill is limited to using the following tools:
Handle Framer API rate limits for Server API and plugin operations. The Server API uses WebSocket, so rate limits apply per-connection. CMS operations are limited by collection size and concurrent writes.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Handle Framer API rate limits for Server API and plugin operations. The Server API uses WebSocket, so rate limits apply per-connection. CMS operations are limited by collection size and concurrent writes.
| Operation | Limit | Notes |
|---|---|---|
| Server API connections | 1 per site | WebSocket, persistent |
| CMS setItems | ~100 items/call | Batch larger sets |
| CMS getItems | No hard limit | Returns all items |
| Plugin API calls | Debounced | Framer throttles internally |
| Publish | ~1/minute | Site publishing |
| Image upload | Concurrent limit | Via CMS image fields |
async function batchSetItems(collection: any, items: any[], batchSize = 100) {
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
await collection.setItems(batch);
console.log(`Synced ${Math.min(i + batchSize, items.length)}/${items.length}`);
if (i + batchSize < items.length) {
await new Promise(r => setTimeout(r, 1000)); // 1s between batches
}
}
}
// Debounce rapid plugin UI interactions
function debounce<T extends (...args: any[]) => any>(fn: T, ms = 300) {
let timer: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
const debouncedSync = debounce(async () => {
await syncCollection();
}, 500);
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let i = 0; i <= maxRetries; i++) {
try {
return await fn();
} catch (err: any) {
if (i === maxRetries) throw err;
const delay = 1000 * Math.pow(2, i);
console.log(`Retry ${i + 1} in ${delay}ms`);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error('Unreachable');
}
| Error | Cause | Solution |
|---|---|---|
| WebSocket disconnected | Connection timeout | Reconnect with backoff |
| setItems slow | Large batch | Split into chunks of 100 |
| Publish rate limited | Too frequent | Wait 60s between publishes |
For security, see framer-security-basics.