Why migrate from Bolt?
Bolt.new builds a working frontend fast — usually Vite + React, sometimes Next.js, with a generated Supabase client. The trade-off is that the generated codebase is a starting point, not a foundation. Auth flows are skeletal, billing is "go wire Stripe yourself", multi-tenancy is absent, and there's no notion of where your data lives or what compliance regime it lands under.
Already CH is the opposite: 16 production-ready modules already wired together, with every default chosen for Swiss data residency.
What carries over without changes
- Your UI components. If Bolt used shadcn/ui + Tailwind (the common default), your components paste straight in.
- Your Supabase project. If Bolt connected you to Supabase Cloud, point Already CH at the same project — or migrate it to self-hosted Supabase on Exoscale for full Swiss residency.
- Your domain model. Tables and RLS policies you defined in Supabase persist; you re-declare them as Drizzle schemas.
What needs migration work
- Vite → Next.js. If Bolt produced a Vite app, you'll move pages into Next.js App Router under
app/(public)/app/(app). The included CLI does most of the mechanical work. - Client-fetched data → Server Components. Bolt's
useEffect+fetchpattern becomes server-sideawait db.query.*withwithOrgScope(). - Stripe → Payrexx. If Bolt suggested Stripe, you'll re-create plans in Payrexx with unique CHF amounts. Idempotent webhooks, 8.1% VAT, TWINT — all wired in Already CH.
- Env vars.
VITE_*becomesNEXT_PUBLIC_*. Secrets move to macOS Keychain viapnpm Already CH secrets push.
Stack mapping
Bolt-generated default → Already CH
Vite + React → Next.js 15 App Router (Server Components)
Supabase Cloud (US/EU) → Supabase self-hosted on Exoscale (CH)
Stripe → Payrexx (CHF, TWINT, PostFinance)
No analytics → Matomo (self-hosted, cookie-free)
No multi-tenancy → Orgs + RLS + withOrgScope()
No nFADP support → /admin/data-register (Art. 12)
.env secrets → macOS Keychain integration
Step-by-step migration
Export or download your Bolt project (or clone the GitHub repo if Bolt synced it). Keep it side-by-side with your new Already CH project.
The included CLI maps Vite pages and assets to the Next.js App Router structure used by Already CH.
pnpm Already CH migrate bolt --source ../my-bolt-app
If you want full Swiss residency, spin up self-hosted Supabase on Exoscale using the Coolify seed JSON in infra/coolify/. pg_dump your Supabase Cloud database and restore it locally.
Create one Payrexx gateway per plan (unique CHF amounts). Set the webhook to /api/webhooks/payrexx. TWINT and PostFinance enable automatically once your Payrexx contract supports them.
Search for useEffect + supabase.from patterns and convert each to an async Server Component using Drizzle with withOrgScope().
Go to /admin/data-register and add one row per processing activity. Done.
Common questions
What if my Bolt app is Next.js already?
Even better — skip the Vite mapping and go straight to copying components and routes into Already CH's route groups.
How long does this take?
Bolt-generated app, small surface: half a day. Add Stripe → Payrexx and self-hosting Supabase on Exoscale: 1–2 days.