Appearance
Getting started
This page takes you from a fresh checkout to the portal running locally on http://localhost:8787. All commands run from cloud/reform-assistant/.
Prerequisites
- Node.js 22 or newer. The locked Wrangler release (4.x) declares
"node": ">=22.0.0"inpackage-lock.json. - npm, which ships with Node.js.
- No Cloudflare or Stripe account is needed for local development. Wrangler emulates D1 and R2 on disk under
.wrangler/. Billing endpoints answer503 billing_not_configureduntil you add Stripe values (see Stripe billing and Stripe setup).
1. Install dependencies
sh
cd cloud/reform-assistant
npm cinpm ci installs exactly what package-lock.json pins. The Worker has no runtime dependencies; the devDependencies are Wrangler, TypeScript, Vitest with the Workers pool, the Workers type definitions, and VitePress for these docs.
2. Create the local database
sh
npm run db:migrate:localThis runs wrangler d1 migrations apply reform-assistant --local, applying migrations/0001_init.sql and migrations/0002_checkout_sessions.sql to the local D1 database. See Architecture for the tables it creates. Re-run it whenever a new migration file is added.
3. Configure local secrets
sh
cp .dev.vars.example .dev.vars.dev.vars is read by wrangler dev and is git-ignored. The example file contains:
| Variable | Purpose | Needed for |
|---|---|---|
APP_URL | Public origin of the portal. Defaults to http://localhost:8787. Used to build Stripe success, cancel, and portal return URLs. (The session cookie's Secure flag follows the request scheme, not this value.) | Always |
STRIPE_SECRET_KEY | Stripe test-mode secret key (sk_test_...). | Checkout and billing portal |
STRIPE_PRICE_MONTHLY, STRIPE_PRICE_QUARTERLY, STRIPE_PRICE_ANNUAL | Stripe Price IDs (price_...) for the three plans. | Checkout, plan detection in webhooks |
HERMES_LINK_TOKEN | Shared secret for the /api/hermes/* endpoints. Any long random string. | Hermes bridge |
STRIPE_WEBHOOK_SECRET (the whsec_... signing secret) verifies webhooks; without it POST /api/stripe/webhook answers 503 billing_not_configured.
Leave the Stripe values empty to explore signup, the inmate form, and the console without payments. Generate a Hermes token with, for example, openssl rand -hex 32.
4. Start the Worker
sh
npm run devnpm run dev runs wrangler dev. Wrangler serves the Worker and the static assets from public/ on http://localhost:8787.
5. Open the pages
| URL | What you get |
|---|---|
/ | Marketing landing page (public/index.html) |
/signup/ | Create an account (name, email, password of at least 10 characters) |
/login/ | Log in |
/console/ | The family console (redirects to /login/ when there is no session) |
A quick end-to-end check without Stripe:
- Open
/signup/and create an account. You land on/console/. - Go to Inmate (
/console/#inmate) and save an inmate. - Go to Plan & billing (
/console/#billing) and click Choose. Without Stripe secrets the console shows "Payments are not switched on yet (sandbox setup pending)." That message is the UI's handling ofbilling_not_configured.
Useful commands
| Command | What it does |
|---|---|
npm run dev | wrangler dev |
npm run db:migrate:local | Apply D1 migrations to the local database |
npm run typecheck | tsc --noEmit (strict) |
npm test | vitest run (see Testing) |
npm run deploy | wrangler deploy (see Cloudflare deployment) |
npm run docs:dev | Serve these docs with VitePress |
npm run docs:build | Build the docs into docs/.vitepress/dist |
npm run docs:preview | Preview the built docs |
Resetting local state
Local D1 and R2 data live under .wrangler/ (git-ignored). Deleting that directory and re-running npm run db:migrate:local gives you an empty database.