Framework
Next.js 16 (App Router)
React 19, TypeScript strict, server components default
For CTOs and founding engineers
Skip the sales tour. This page is the architectural document — stack choices, data-migration approach, cutover plan, what we keep, what we don’t touch, and the failure modes we plan for. No platform-bashing. No SOWs. If something here doesn’t match how you’d build it, push back on the call.
Stack we build on
Every choice optimises for one thing: a senior engineer at any salary band should be able to read it and ship within a week of joining.
Framework
Next.js 16 (App Router)
React 19, TypeScript strict, server components default
Data layer
Postgres + Drizzle
Schema-first migrations, type-safe queries, runs anywhere
Auth + access
Clerk or NextAuth v5
Whichever fits your existing setup; both portable
Background jobs
Inngest
Replaces Bubble scheduling; durable, observable, retryable
Hosting
Vercel + Supabase
Default to portable infra; we can deploy to your AWS / GCP if you prefer
Source
Your GitHub org · day one
We push as collaborators on your repo. You own everything from commit 1.
How we approach a rebuild
Step 01
Day 0 · free
We point our analysis pipeline at your export and read every workflow, every data type, every plugin. You get the McKinsey-grade report + a personalised tailwind.config.js extracted from your design system + a live preview deployed to Vercel — all before any commercial conversation.
Step 02
Week 1
We rebuild your Bubble data model 1:1 in Postgres with Drizzle migrations. Foreign keys, indices, and the privacy rules that survived translation are documented. Old Bubble row IDs are preserved as columns so we can dual-write during cutover.
Step 03
Week 1
Bubble doesn't let us export password hashes. We use Clerk or NextAuth v5 with one-time-passcode + magic link as the migration path — your users reset on first login or stay logged in via session token. No 'silent' rebuild user reset.
Step 04
Weeks 2-3
The 5-10 workflows that ARE your product — billing, message send, content publish, whatever moves revenue. Each ships as its own PR with its own demo loom. Inngest replaces Bubble scheduling for cron + long-running tasks (no 300-second timeout).
Step 05
Weeks 3-5
Once spine workflows are stable on code, we start writing every mutation to BOTH Bubble (read-only sync) and Postgres. This lets you A/B test, fall back instantly, and prove parity before cutover.
Step 06
Weeks 3-5 (parallel)
Long tail of pages — most are variations of a pattern, not net-new. We batch by similarity (all list-with-filter pages together, all edit-record forms together) so each batch ships in days. Tailwind config is seeded from your existing palette so brand survives.
Step 07
Final week
DNS flip + Bubble app frozen in read-only. We've been dual-writing for 2+ weeks so cutover is a 30-min window with active monitoring on a call. Bubble app stays read-only for 30 days as a fallback you can revert to in 2 minutes.
Step 08
After cutover
We're on-call for any production issue 30 days post-cutover at no extra cost. Daily Slack standup, 3am pager rotation if needed. After 30 days you keep everything; we're an email away if you want us back.
Hybrid · the middle path
The default play for production teams. Hot paths (signup, billing, spine workflows, public pages) move to code where SOC2, performance and hiring matter. Cold paths (admin dashboards, internal CRM, one-off ops tools) stay on Bubble. We’ll score every page on the call and tell you which side it belongs.
What we don’t touch
Same energy as the "migrate now if / stay on Bubble if" line on the main page. Credibility-by-refusal.
30 minutes with Greg · no slides, no pitch. Open your repo on screen, walk through the architecture, ask anything. If we’d build it differently than you would, you’ll know in 5 minutes.