Minimal concierge flow for uploading a vet invoice, collecting payment, and reviewing submissions.
npm install
npm run devCreate a .env file locally and set these values:
DATABASE_URL=postgresql://USER:PASSWORD@HOST:PORT/DATABASE
APP_URL=http://localhost:3000
TURNSTILE_SECRET_KEY=...
NEXT_PUBLIC_TURNSTILE_SITE_KEY=...
R2_ACCOUNT_ID=...
R2_ACCESS_KEY_ID=...
R2_SECRET_ACCESS_KEY=...
R2_BUCKET_NAME=...
STRIPE_SECRET_KEY=...
STRIPE_WEBHOOK_SECRET=...
STRIPE_PRICE_ID=...
ADMIN_TOKEN=...
- Create a Railway Postgres database and copy the connection string into
DATABASE_URL. - Run the Prisma migration (local) and deploy in production:
npm run prisma generate
npm run prisma migrate dev
npm run migrate:deployMigration files live in prisma/migrations.
- Create an R2 bucket and credentials with read/write access.
- Set
R2_ACCOUNT_ID,R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY, andR2_BUCKET_NAME. - The app uses presigned PUT for uploads and presigned GET for admin invoice access.
- Create a Turnstile site key and secret key.
- Client-side uses
NEXT_PUBLIC_TURNSTILE_SITE_KEY. - Server verifies
TURNSTILE_SECRET_KEYinside/api/upload/presign.
- Create a product + price, then set
STRIPE_PRICE_ID. - Set
STRIPE_SECRET_KEYandSTRIPE_WEBHOOK_SECRET. - Configure webhook endpoint to
/api/stripe/webhook.
- Open
/admin. - Paste
ADMIN_TOKENto view orders. - Use the action buttons to update status or download invoice.
npm run dev- start Next.js dev servernpm run build- build the appnpm run start- start production servernpm run prisma- Prisma CLInpm run migrate:deploy- deploy migrations