Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Deploy Framer integrations to Vercel, Fly.io, and Cloud Run platforms. Use when deploying Framer-powered applications to production, configuring platform-specific secrets, or setting up deployment pipelines. Trigger with phrases like "deploy framer", "framer Vercel", "framer production deploy", "framer Cloud Run", "framer Fly.io".
.claude/skills/jeremylongshore-framer-deploy-integration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -2% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 25% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -3% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 26% | 0% |
Deploy Framer Server API integrations (CMS sync services, webhook handlers) to cloud platforms. Framer sites themselves are hosted by Framer — this covers deploying your backend services that interact with Framer.
typescript// api/sync-framer.ts — Vercel serverless function import type { VercelRequest, VercelResponse } from '@vercel/node'; import { framer } from 'framer-api'; export default async function handler(req: VercelRequest, res: VercelResponse) { if (req.method !== 'POST') return res.status(405).end(); const client = await framer.connect({ apiKey: process.env.FRAMER_API_KEY!, siteId: process.env.FRAMER_SITE_ID!, }); const { items, collectionName } = req.body; const collections = await client.getCollections(); const col = collections.find(c => c.name === collectionName); if (!col) return res.status(404).json({ error: 'Collection not found' }); await col.setItems(items); await client.publish(); res.json({ synced: items.length, published: true }); }
bashvercel env add FRAMER_API_KEY production vercel env add FRAMER_SITE_ID production vercel --prod
bashfly secrets set FRAMER_API_KEY=framer_sk_... fly secrets set FRAMER_SITE_ID=abc123 fly deploy
typescript// api/webhook-handler.ts — receive webhooks from your CMS, sync to Framer export default async function handler(req, res) { const { event, data } = req.body; if (event === 'content.published') { const client = await framer.connect({ apiKey: process.env.FRAMER_API_KEY!, siteId: process.env.FRAMER_SITE_ID! }); // Sync updated content to Framer CMS const col = (await client.getCollections()).find(c => c.name === 'Blog Posts'); if (col) await col.setItems([{ fieldData: data }]); await client.publish(); } res.json({ ok: true }); }
For webhook patterns, see framer-webhooks-events.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 20,639 | 17,019 | -18% | 1 | 1 | 0% | 3,368 | 3,291 | -2% | 0 | 0 | — |
case-02 | fail→pass | 21,677 | 20,189 | -7% | 1 | 1 | 0% | 3,070 | 3,828 | +25% | 0 | 0 | — |
case-03 | fail→pass | 15,412 | 11,381 | -26% | 1 | 1 | 0% | 1,925 | 1,871 | -3% | 0 | 0 | — |
case-04 | fail→pass | 6,808 | 8,834 | +30% | 1 | 1 | 0% | 1,171 | 1,354 | +16% | 0 | 0 | — |
case-05 | fail→fail | 13,025 | 2,789 | -79% | 1 | 1 | 0% | 1,384 | 1,207 | -13% | 0 | 0 | — |
case-06 | fail→pass | 6,752 | 4,643 | -31% | 1 | 1 | 0% | 1,137 | 1,430 | +26% | 0 | 0 | — |
case-07 | fail→pass | 13,559 | 14,434 | +6% | 1 | 1 | 0% | 2,331 | 2,370 | +2% | 0 | 0 | — |
case-08 | pass→pass | 8,722 | 5,355 | -39% | 1 | 1 | 0% | 1,563 | 1,637 | +5% | 0 | 0 | — |
case-09 | pass→pass | 15,607 | 8,583 | -45% | 1 | 1 | 0% | 1,813 | 2,233 | +23% | 0 | 0 | — |
case-10 | fail→fail | 15,265 | 13,880 | -9% | 1 | 1 | 0% | 1,740 | 2,278 | +31% | 0 | 0 | — |
case-11 | pass→pass | 16,133 | 8,886 | -45% | 1 | 1 | 0% | 2,090 | 1,384 | -34% | 0 | 0 | — |
case-12 | fail→pass | 13,932 | 3,879 | -72% | 1 | 1 | 0% | 1,390 | 1,352 | -3% | 0 | 0 | — |
case-13 | pass→pass | 7,934 | 9,151 | +15% | 1 | 1 | 0% | 1,340 | 1,373 | +2% | 0 | 0 | — |
case-14 | pass→pass | 8,562 | 3,189 | -63% | 1 | 1 | 0% | 1,486 | 1,232 | -17% | 0 | 0 | — |
case-15 | pass→pass | 7,631 | 7,836 | +3% | 1 | 1 | 0% | 1,262 | 1,210 | -4% | 0 | 0 | — |
case-16 | pass→pass | 8,414 | 11,237 | +34% | 1 | 1 | 0% | 1,545 | 1,907 | +23% | 0 | 0 | — |
case-17 | fail→pass | 9,077 | 10,231 | +13% | 1 | 1 | 0% | 1,298 | 1,710 | +32% | 0 | 0 | — |
case-18 | pass→pass | 12,068 | 9,531 | -21% | 1 | 1 | 0% | 1,393 | 2,461 | +77% | 0 | 0 | — |
case-19 | pass→pass | 9,569 | 5,313 | -44% | 1 | 1 | 0% | 1,887 | 1,740 | -8% | 0 | 0 | — |
case-20 | fail→pass | 6,399 | 2,639 | -59% | 1 | 1 | 0% | 1,200 | 1,144 | -5% | 0 | 0 | — |
case-21 | fail→pass | 16,802 | 7,731 | -54% | 1 | 1 | 0% | 2,442 | 2,182 | -11% | 0 | 0 | — |
case-22 | pass→pass | 13,837 | 12,616 | -9% | 1 | 1 | 0% | 1,823 | 2,291 | +26% | 0 | 0 | — |
case-23 | pass→pass | 18,776 | 11,818 | -37% | 1 | 1 | 0% | 2,831 | 3,231 | +14% | 0 | 0 | — |
case-24 | pass→pass | 14,447 | 15,947 | +10% | 1 | 1 | 0% | 2,414 | 4,967 | +106% | 0 | 0 | — |
case-25 | pass→fail | 25,717 | 22,958 | -11% | 1 | 1 | 0% | 4,683 | 5,883 | +26% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 25 cases were attempted. The headline lift of +36 percentage points is the difference between those two pass rates over the 25 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.