Deployment
Deploy the vantezzen/pay Next.js app and connect it to the provider service.
vantezzen/pay's public surface is a standard Next.js app. Provider API keys live
in the separate provider service; the web app calls it through
PAY_PROVIDER_SERVICE_URL.
Vercel
- Import the repository.
- Set the environment variables from Environment variables.
- Make sure the provider service is deployed and reachable by the web app.
- Deploy.
- Run
bun run db:migrateonce against production. - Visit
/registerand create your admin account. - Set
PAY_ALLOW_SIGNUPS=false.
The build script generates the shadcn registry JSON before building the app, so
the registry is served from /r.
With Vercel Services, the included vercel.json defines a web service and a
provider-service service. The provider service URL is injected into the web app
as PAY_PROVIDER_SERVICE_URL over Vercel's internal service binding.
Docker Compose
The repository includes a production web image (Dockerfile), encrypted-key
provider service, and Postgres in docker-compose.yml. Create a root .env
from the values in Environment variables, then:
docker compose --profile secure build
docker compose --profile secure up -dAll application services (web, provider-service, migrate) use the
secure profile. Running docker compose up without --profile secure starts
only Postgres. Always pass --profile secure for a full stack.
Migrations run automatically before web starts - docker compose up is all
you need. The migrate service uses drizzle's idempotent migration runner, so
re-running up on an already-migrated database is safe.
The web image is built with NEXT_PUBLIC_APP_URL, because Next.js embeds public
environment variables in browser code at build time. Set the final HTTPS URL
before build, then rebuild the image if that URL changes.
The Compose file exposes web on port 3000. The provider service is on an
internal network only - it is not published to the host, and only the web
container can reach it. Put a TLS-terminating reverse proxy in front of the web
service.
Other hosts
Your host must support:
- Node-compatible Next.js runtime.
- Long enough request handling for provider SDK calls.
- HTTPS public URL for webhooks.
- Persistent Postgres database.
- Environment variables.
- Private network access to the provider service, or a protected provider
service URL with
PAY_PROVIDER_SERVICE_SECRET.
Trusted proxy
Per-IP protections (anonymous wallet creation throttling, publishable-key rate
limits) read the client address from x-forwarded-for. That header is only
trustworthy behind a proxy that overwrites it - Vercel and Cloudflare do,
and a well-configured nginx/Caddy does too. Don't expose the Node process to
the internet directly, or clients can spoof the header and bypass those
limits.
Public URL
The public URL is important. It is used for:
- Dashboard auth callbacks.
- Provider webhook URLs.
- Hosted checkout success/fallback pages.
- Consumer app registry install URLs.
- API calls from consuming apps.
If the domain changes, update BETTER_AUTH_URL, NEXT_PUBLIC_APP_URL, provider
webhooks, and consumer app environment variables.