You built a working app in a vibe-coding platform. Now you want the option to deploy anywhere — your own VPS, multiple stores, multiple registries — instead of being limited to one platform's defaults. This guide walks you through that handoff using
create-starter.This isn't about "escaping" any platform. As of 2026-05, Vercel, Cloudflare, and Netlify are all evolving into "Agentic Infrastructure" providers — each excellent for the workloads they target. Graduation just gives you vendor diversity: the freedom to pick a different target per app without rewriting your CI/CD every time.
Languages: English (this file) · 한국어
This guide is for you if:
- ✅ Your app would benefit from a different deploy target (your own VPS, GHCR, Cloudflare Workers/Pages, App Store, Chrome Web Store, npm, PyPI…) than your current platform's default
- ✅ You want GitHub Actions logs for CI/CD steps the platform hides
- ✅ You want predictable CI minutes (GitHub Actions: free for public repos, ~$0.30/hr private) instead of per-build platform billing
- ✅ You want CI-side supply-chain security gates (gitleaks, CodeQL, OIDC publish, supply-chain attestations) before code reaches production
- ✅ Your code is already in GitHub (Lovable's sync, Bolt's export, v0's git panel)
It is not for you if:
- ❌ You're happy with the platform's auto-deploy and don't need GitHub Actions
- ❌ Your app fits exactly one platform's stack (e.g., Next.js on Vercel) and you have no other reason to add complexity
Five steps. Each runs in your terminal. None of them require leaving your existing AI session — every CLI command is also exposed as an MCP tool, so you can ask Claude Code to run them for you.
1. Diagnose → audit, audit-cd, audit-security
2. Pick a target → docker-deploy / cloudflare-pages / npm-package / …
3. Lift CI/CD → copy .github/workflows from the matching starter
4. Wire secrets → repo secrets via gh secret set
5. Verify → re-run audit; tag a release
Clone your platform's GitHub repo locally and run the three audit primitives.
git clone https://github.com/<you>/<your-app>.git
cd <your-app>
npx -y starter-series audit
npx -y starter-series audit-cd
npx -y starter-series audit-securityYou'll get three reports:
- audit — closest matching Starter Series template, CHANGELOG drift vs merged PRs, version-bump status, publish-workflow kind. Most vibe-coded apps start with
Matched starter: (none)andPublish workflow: missing— that's expected. - audit-cd — current state of each destination registry. Will report
not-foundfor npm/PyPI/Open VSX/AMO/GitHub Releases until you publish. - audit-security —
SOFTis typical at this stage. The recommendations under each MISSING/PARTIAL row tell you exactly what to add.
Tip: Inside Claude Code, just ask: "audit this repo with starter-series". The MCP tools run automatically.
Each vibe-coding platform has a sensible default (Lovable → Netlify/Vercel, Bolt → Netlify, v0 → Vercel). Graduation gives you the option to ship to a different target when one of your apps would be a better fit elsewhere. Pick the matching starter:
| Your app | Recommended target | Starter |
|---|---|---|
| Next.js / Vite / React app on your own VPS | Docker + GHCR + SSH | docker-deploy |
| Static site (HTML/CSS + light JS) | Cloudflare Pages | cloudflare-pages |
| Claude / voice agent (server-side runtime) | Cloudflare Workers + Claude Managed Agents | docker-deploy (adapter) — see note below |
| Browser extension (already MV3) | CWS + AMO | browser-extension |
| Cross-platform desktop app | electron-builder + code signing | electron-app |
| Mobile app | Expo + EAS | react-native |
| Discord/Telegram bot | Docker + Railway/Fly | discord-bot / telegram-bot |
| Reusable library | npm OIDC trusted publishing | npm-package |
| Python tool / agent | PyPI OIDC trusted publishing | python-mcp-server |
Claude / voice agent on Cloudflare Workers (added 2026-05) — Anthropic and Cloudflare announced Claude Managed Agents on Cloudflare Workers (2026-05-19); the
@cloudflare/voiceSDK shipped a week later (2026-05-26). Two paths today, both via the existingdocker-deploystarter:(a) Quick Wrangler config — copy this
wrangler.tomlinto your repo root (replaces the Dockerfile path):name = "my-claude-agent" main = "src/index.ts" compatibility_date = "2026-05-27" [vars] # CLAUDE_API_KEY set via: wrangler secret put CLAUDE_API_KEY [observability] enabled = trueThen add
wrangler deployto the deploy step ofdocker-deploy-starter's.github/workflows/deploy.ymlin place of the SSH-to-VPS step. Secret:CLOUDFLARE_API_TOKEN.(b) Container path — keep
docker-deploy-starterunchanged and run the container on any host that speaks the Claude Managed Agents protocol; trade-off is no Workers-native cold start.A dedicated
cloudflare-workers-agentstarter is on the roadmap once the Managed Agents API stabilizes (track starter-series/cloudflare-pages-starter#1).
Most common path: vibe-coded React/Next/Vite SPA → docker-deploy (any VPS you own) or cloudflare-pages (free, unlimited bandwidth).
You don't need to scaffold a fresh project and copy your code over. Instead, lift the .github/workflows/ directory and supporting files from the matching starter into your existing repo.
# Pick a target, e.g. docker-deploy
TARGET=docker-deploy
# Grab just the CI infrastructure
git clone --depth=1 https://github.com/starter-series/${TARGET}-starter.git /tmp/starter
cp -r /tmp/starter/.github .
cp /tmp/starter/Dockerfile* . # if applicable
cp /tmp/starter/.gitleaks.toml . 2>/dev/null || true
cp /tmp/starter/.dockerignore . 2>/dev/null || true
cp /tmp/starter/CHANGELOG.md . # adopts the same release notes format
# Open the workflow files and replace placeholder repo names
# Look for YOUR_USERNAME, YOUR_REGISTRY, etc.# Scaffold a fresh sibling
npx -y starter-series my-fresh --template ${TARGET}
# Compare files, copy what you want
diff -r my-fresh/.github .github"Add the docker-deploy starter's
.github/workflows/and Dockerfile to this repo. Don't touch my app code. Update placeholder owner/repo references to match the current remote."
The agent will fetch the files via the MCP tools and report what changed.
Every deploy target needs its own secret set. Common ones:
| Target | Required secrets | OIDC available? |
|---|---|---|
| docker-deploy | DEPLOY_SSH_HOST, DEPLOY_SSH_USER, DEPLOY_SSH_KEY |
No |
| npm-package | NPM_TOKEN (or none with OIDC trusted publishing) |
✅ Yes, set up at npmjs.com |
| python-mcp-server | (none with OIDC) | ✅ Yes, set up at PyPI |
| browser-extension | CWS_CLIENT_ID, CWS_CLIENT_SECRET, CWS_REFRESH_TOKEN, AMO_JWT_ISSUER, AMO_JWT_SECRET |
No |
| vscode-extension | VSCE_PAT, OVSX_PAT |
No |
| electron-app | APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID, signing cert + password |
No |
| react-native | EXPO_TOKEN |
No |
| cloudflare-pages | CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID |
No |
# Example: set npm OIDC-free secrets
gh secret set DEPLOY_SSH_HOST -b "your.vps.example.com"
gh secret set DEPLOY_SSH_USER -b "deploy"
gh secret set DEPLOY_SSH_KEY < ~/.ssh/deploy_id_ed25519
# For OIDC-enabled targets (npm, PyPI), NO secrets needed — just set up
# the publisher on the registry side. See each starter's README for the link.Re-run the audit primitives. Targets should now look like this:
audit → Ship-ready: ATTENTION (only CHANGELOG drift remaining, expected)
audit-security → Overall: HARDENED (8/8 present) or NEEDS-ATTENTION (1-2 missing)
audit-cd → All destinations report not-found (because nothing's been published yet)
Now ship your first release:
# Update CHANGELOG.md Unreleased section with your initial entries
git add . && git commit -m "chore: lift CI/CD from starter-series/${TARGET}-starter"
git push origin main
# Tag a release — most starters trigger publish on tag push
git tag v0.1.0
git push --tagsWatch the workflow run, then re-run audit-cd:
npx -y starter-series audit-cd
# → npm/Open VSX/AMO/GH Releases now report in-syncIf something fails on the first run, the CI logs will tell you exactly which secret or config is wrong. The starters are designed so the error messages are actionable, not opaque platform errors.
Search for @vercel/analytics in your code and either remove it (and the corresponding tag in app.tsx/layout.tsx) or wire it to a non-Vercel analytics provider (Plausible, Umami self-hosted).
WebContainer is Bolt's browser sandbox. Any import * from '@webcontainer/api' won't run outside Bolt. Replace with native Node equivalents (fs/promises, child_process) or remove if it was just for in-browser preview.
v0 generates app/api/* routes that assume Vercel's edge runtime. If you're moving to docker-deploy, change export const runtime = 'edge' to 'nodejs' and verify your DB driver works in Node (most do).
All three platforms commonly pair with Supabase. Supabase has no platform lock-in — your existing NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY work from any deploy target. Just move them from platform env vars to repo secrets.
Vibe platforms sometimes commit .env.local to GitHub. The first time gitleaks runs in CI, it'll flag this. Rotate the leaked keys (don't just rebase), then add .env* to .gitignore and remove from history via git filter-repo --path .env.local --invert-paths.
After completing all five steps, you have:
| Capability | Vibe platform | After graduation |
|---|---|---|
| Deploy target | Platform-locked | Anywhere (VPS, Cloudflare, npm, app stores) |
| CI logs | Hidden | GitHub Actions with full step-level visibility |
| Secret scanning | Limited | gitleaks + GitHub native secret scanning on every push |
| Static analysis | None | CodeQL on every PR |
| AI security review | None | anthropics/claude-code-security-review on every PR |
| Publish auth | Platform owns | OIDC trusted publishing (no long-lived tokens) |
| Release notes | Manual | Auto-generated from PR titles + CHANGELOG |
| Rollback | Platform UI | git revert + re-tag |
| Cost | Platform token billing | Free CI minutes for public repos, ~$0.30/hr private |
- Stuck on a specific platform? Open an issue: starter-series/create-starter/issues. Include the export source (Lovable/Bolt/v0) and which step blocked you.
- Want the AI to drive the whole thing? Install
create-starteras a Claude Code plugin:/plugin marketplace add starter-series/create-starter && /plugin install create-starter@starter-series. Then say "graduate this Lovable export to docker-deploy" and the agent handles steps 1–4. - More starters? See the full list. If your case isn't covered, the
docker-deploystarter is language- and framework-agnostic — the universal fallback for any app you want to containerize.