Getting started

From clone to running locally in five minutes.

Prerequisites

  • Bun — the only package manager this repo uses
  • A Google Cloud project, for OAuth credentials (Google sign-in is required; GitHub and emailed sign-in codes are optional extras)
  • A Cloudflare account — needed to deploy, not to run locally

Setup

bun install
bun run db:migrate:local
bun run dev            # http://localhost:3000

Secrets live in .dev.vars, which is gitignored. Start from the key list with cp .dev.vars.example .dev.vars, then fill in at least BETTER_AUTH_SECRET (openssl rand -base64 32) and the two Google OAuth values before signing in. Env is read at boot, so restart the dev server after editing it. Keep a copy of every key in a password manager: a key that lives only in a terminal or a dashboard is a key that gets lost.

The dev server runs your code inside workerd with local D1 and R2 bindings, so local behavior matches production. Local state lives under .wrangler/state, also gitignored.

If you have Claude Code, /setup does all of the above and creates your first admin user; /google-oauth, /stripe and /deploy handle the account setup that has to happen in a browser.

Make yourself an admin

Sign in once, then flip your row:

bunx wrangler d1 execute DB --local \
  --command "UPDATE user SET role='admin' WHERE email='you@example.com';"

/admin is now reachable from the sidebar.

Before the first deploy

Work through src/config/app-config.ts — the name, canonical URL, support address and legal entity reach the marketing pages, every transactional email and the Terms and Privacy pages. Then src/config/plans.ts, whose product ids are placeholders until you create a payment catalog.

Deploy

wrangler d1 create shipkit            # put the id into wrangler.jsonc
wrangler r2 bucket create shipkit-files
bun run db:migrate:remote          # migrations are applied by hand, never by CI
wrangler secret put BETTER_AUTH_SECRET   # repeat for the other secrets
bun run deploy

CI refuses to deploy while migrations are pending, so apply them first.