# Recipe: v0

For an app built in v0 by Vercel: a Next.js App Router project that runs and deploys on Vercel. The code is the [Next.js recipe](https://checkouts.md/recipes/nextjs.md); this file covers what's different in v0 and the prompt to paste. [The playbook](https://checkouts.md/playbook.md) has the reasons and every error code.

| | |
|---|---|
| Server code runs in | Next.js route handlers on Vercel Functions |
| Database | The project's database integration (Neon or Supabase through Vercel, for example), as `DATABASE_URL` |
| Secrets | The project's environment variables in v0 and Vercel. Never `NEXT_PUBLIC_` variables |
| Webhook URL | The deployment's address + `/api/webhooks/railbed` |
| Connect | Keys entered as environment variables (below), or `npx checkouts.md login` once the project is on a computer |

## 1. Connect

v0's chat can't run `npx` on the person's computer. Pick the first that applies:

1. **The project is also on a computer with a coding agent** (v0 can push a project to GitHub or let you download it): run `npx checkouts.md login --env-path .env.local --live-to env:.env.railbed` there, as in the Next.js recipe. The Vercel CLI must be linked to the project.
2. **Otherwise**, the approval happens in Railbed's dashboard. Ask the person to sign in or sign up at https://app.railbed.io/signup, switch on **Test mode**, open **Developers**, **Create key** (purpose Checkout API, Full access, named "v0"), and add it as the environment variable `RAILBED_SECRET_KEY` in v0's project settings (or the Vercel project's Environment Variables, for Preview and Development). Never into the chat.

> To connect payments I need a Railbed key, which only you can create. Sign in at app.railbed.io (or create an account), turn on Test mode in the menu at the top left, open Developers and choose Create key. Then add it as an environment variable named RAILBED_SECRET_KEY in this project's settings, not in this chat. Nothing is charged in Test mode.

## 2. The prompt to paste

```text
Read checkouts.md/recipes/v0.md and add a Railbed checkout to this app, following the Next.js recipe it links to.
Sell: Pro plan for 49.00 USD.
Use route handlers for the checkout and the webhook. Keep RAILBED_SECRET_KEY and RAILBED_WEBHOOK_SECRET only
in environment variables (never NEXT_PUBLIC_), never in code or in this chat. Mark an order paid only from a
verified Railbed webhook after re-reading the payment. Test it in Railbed's Test mode before anything goes live.
```

## 3. What gets built

The [Next.js recipe](https://checkouts.md/recipes/nextjs.md) as it is: `db/railbed.sql`, `lib/products.ts`, `lib/db.ts`, `lib/railbed.ts`, `lib/orders.ts`, `app/api/checkout/route.ts`, `app/api/webhooks/railbed/route.ts`, `app/checkout/success/page.tsx` with `refresh.tsx`, and `components/PayButton.tsx`. In v0:

- Add a PostgreSQL database through v0's or Vercel's integrations if the project has none, and use its connection string as `DATABASE_URL`. Some integrations name it `POSTGRES_URL`: then change `lib/db.ts` to read `process.env.DATABASE_URL ?? process.env.POSTGRES_URL`. Run `db/railbed.sql` against it.
- Set `APP_URL` to the deployment's `https://` address.

## 4. The webhook endpoint

Webhooks need a deployed address Railbed can reach: deploy a Preview with the Test key, then create the endpoint for `https://<preview-address>/api/webhooks/railbed`. With a computer (step 1, option 1): `npx checkouts.md webhook <address> --env-path .env.local`, then add `RAILBED_WEBHOOK_SECRET` to the Preview environment from `.env.local` without printing it (`grep '^RAILBED_WEBHOOK_SECRET=' .env.local | cut -d= -f2- | tr -d '\n' | vercel env add RAILBED_WEBHOOK_SECRET preview`). Without one, ask the person to add the endpoint in Railbed (Developers → **Add endpoint**), **Reveal** its signing secret and add it as the environment variable `RAILBED_WEBHOOK_SECRET`. Redeploy after adding variables.

Vercel Deployment Protection, which new projects often have on for previews, answers Railbed's requests with `401`. Test against a deployment that isn't protected (turn protection off for previews while testing, or test locally with a tunnel as in the Next.js recipe). Don't put a protection-bypass token in the endpoint's address: that makes the address itself a credential.

## 5. Test it

1. On the Preview deployment, click the Pay button; Railbed's checkout opens.
2. Enter any email, choose Pay, and choose **Simulate successful payment** on the test provider page.
3. Check: the success page says the order is confirmed; the function logs show `Railbed webhook payment.paid evt_…: fulfilled`; the order is `paid` in the database; Railbed's dashboard (Test mode) shows **Webhook delivered** on the payment.
4. Try **Simulate an underpayment** with a new order: the order shows `held` and nothing is granted.
5. Record the payment id under Evidence in `CHECKOUTS.md`.

## 6. Go live

1. The business adds a payout wallet in Railbed's Settings.
2. Put the Live key in the Production environment (pushed from `.env.railbed` as in the [Next.js recipe's go-live](https://checkouts.md/recipes/nextjs.md#6-go-live), or created in Railbed's Developers in Live mode and added by the person), set `APP_URL` to the production address, and deploy to Production.
3. Add the Live endpoint for `https://<production-address>/api/webhooks/railbed` (with a computer: `npx checkouts.md webhook <address> --live --live-to env:.env.railbed`, then push its secret as the Next.js recipe does; without one, the person adds it in Railbed's Developers in Live mode) and its secret to the Production environment as `RAILBED_WEBHOOK_SECRET`. Redeploy.
4. Check: `curl -s -o /dev/null -w '%{http_code}\n' -X POST https://<production-address>/api/webhooks/railbed -d '{}'` answers `400`.
5. Set `mode: live` in `CHECKOUTS.md`. The first real payment is the Live evidence.

## 7. CHECKOUTS.md

As in the [Next.js recipe](https://checkouts.md/recipes/nextjs.md#7-checkoutsmd).

## Platform notes

These describe v0 and Vercel as they work at the time of writing; if they differ, follow their documentation and keep the rules.

- Environment variables are per environment (Development, Preview, Production): Test values in Development and Preview, Live values in Production only.
- A change to environment variables applies to the next deployment, not the running one.
