Walkthroughs / 2026-09-01
From clone to deployed, start to finish
Every step between `bun install` and a live domain — what you configure, in what order, and which steps you genuinely cannot automate.

This is the whole path, in the order the dependencies actually run. Nothing here is optional except where it says so.
1. Run it (5 minutes)
bun install
bun run db:migrate:local
bun run dev
You now have the app at localhost:3000 with local D1 and R2 — but you cannot
sign in yet, because Google is the only sign-in method.
2. Google OAuth (10 minutes, mostly browser)
Create an OAuth client in Google Cloud with redirect URI
http://localhost:3000/api/auth/callback/google. Put the id and secret in
.dev.vars, and the id also in appConfig.googleClientId — One Tap runs
in the browser and needs it public. Restart the dev server; env is read at
boot.
Sign in, then promote yourself:
bunx wrangler d1 execute DB --local \
--command "UPDATE user SET role='admin' WHERE email='you@example.com';"
3. Make it yours (30 minutes, and worth every one)
src/config/app-config.ts first: name, canonical URL, support address, legal
entity. Those values reach the marketing pages, every transactional email, and
the Terms and Privacy pages — the legal entity is printed verbatim, so fill it
in before you take a payment.
Then src/config/plans.ts. The comment at the top explains the ladder: packs
sell at list price, subscriptions below it, and plans.test.ts fails the build
if a tier ever drops under a margin floor. Set CREDIT_COST_CENTS from a
measurement, not a guess.
4. Payments (20 minutes)
Create the catalog — one product per tier, one recurring price per interval —
and paste the ids into plans.ts, replacing the REPLACE_ME placeholders. Put
the secret key and webhook secret in .dev.vars and set PAYMENT_PROVIDER.
Test locally with the Stripe CLI forwarding to your dev server:
bun run stripe:listen
Buy something with a test card and watch the ledger move. Until a provider key exists the purchase buttons say so instead of starting a checkout, so this step is safe to defer.
5. Deploy (15 minutes)
wrangler d1 create shipkit # id → wrangler.jsonc
wrangler r2 bucket create shipkit-files
bun run db:migrate:remote
grep -v '^#' .prod.vars | grep = | wrangler secret bulk
bun run deploy
Migrations are applied by hand, never from CI — a schema change is a deliberate, watched step, and the deploy job refuses to ship code whose migrations are still pending.
6. The things only you can do
A second Google OAuth client for the production origin. A webhook endpoint in
the payment dashboard pointing at <your-domain>/api/webhooks/stripe. A
verified sending domain in Resend. These are browser steps with no API worth
scripting — which is exactly why the repo ships Claude Code skills that walk
you through them and verify the result instead of pretending they do not exist.
ShipKit
