flowingkhaosSign in
Deploy your own Travolestep 7 of 7 · 0 of 14 carriedSign in to keep it
Step 7 of 7 · weight 2 · about 20 minutes

Verify it in production

Prove it works, in production

Run through this list on the production URL, not on localhost:

  • /signup created your account, and a second attempt with another address is refused.
  • You can create a trip with a budget.
  • You can add an expense in a foreign currency, and the Canadian total is right.
  • You can attach a PDF receipt, and download it again from the expense page.
  • The dashboard shows the trip under, near or over budget.
  • Export → Excel downloads a .xlsx file with your expense in it.
  • Settings → Invitations creates a link bound to one address.

The PDF export on Vercel

The PDF report is printed by a headless Chromium through playwright. Vercel functions do not include a Chromium binary, so on a plain deploy this export is expected to fail while everything else works. Test it, and if it fails you have two honest options:

  1. Use a serverless Chromium build. Add @sparticuz/chromium and pass its executablePath() to chromium.launch() in lib/report/pdf.ts. Keep playwright for local runs.
  2. Host the app in a container. On Railway, Fly.io or your own server, install Chromium in the image with bunx playwright install --with-deps chromium. The code needs no change.

Option 1 keeps you on the free tier. Option 2 costs a few dollars a month and removes the difference between your laptop and production.

Close the bootstrap door for good

It already closed itself when you signed up: the first account claims a one-row latch that is never released, even if every user is deleted. You can still set AUTH_ALLOW_FIRST_USER=false in Vercel and redeploy, so the setting says what the database already enforces.

You are done

You have a deployed Travole with your own database, your own receipt storage, and you as its only admin. From here:

  • read lib/auth/policy.ts to see how one function guards every way to create an account;
  • read lib/report/shape.ts to see how one data shape feeds three outputs;
  • change lib/db/schema.ts, run bun run db:generate, and ship your first migration — migrate first, deploy second.
The gate · a reading check closes this stepweight 2 of Σw 14

Check what you read in “Verify it in production”

The questions are public; scoring them needs an account. They were generated once for this step, and the key never leaves the server.

Loading the check…

All 7 stepsGo to the gate

Luke Sidney writes and builds everything here, alone, in the open. lukesidney.me