Keeps your shadcn/ui + Tailwind components
Vite → Next.js (App Router) migration script
Stripe → Payrexx (CHF, TWINT)
Data stays in Switzerland 🇨🇭

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 + fetch pattern becomes server-side await db.query.* with withOrgScope().
  • 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_* becomes NEXT_PUBLIC_*. Secrets move to macOS Keychain via pnpm 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

01
Pull your Bolt project locally

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.

02
Run the Vite → Next.js helper

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
03
Move Supabase to Exoscale (optional but recommended)

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.

04
Replace Stripe with Payrexx

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.

05
Convert client fetching to Server Components

Search for useEffect + supabase.from patterns and convert each to an async Server Component using Drizzle with withOrgScope().

06
Fill the nFADP register

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.