Deploying — Vercel + Neon + Fly
Hook
The last mile of “ship it” is three providers, glued by environment variables. Vercel hosts the static + Next.js site. Neon hosts Postgres. Fly or Render hosts the FastAPI service. Each is one signup + one config; all together cost $0 to start.
Concept
The minimum prod stack:
| Component | Service | Free tier |
|---|---|---|
Static site (1pride.app) | Vercel | yes, generous |
App (app.1pride.app) | Vercel | yes, generous |
| Postgres | Neon | yes, 0.5GB |
| FastAPI | Fly.io or Render | small free tier |
Environment variables connect them. From the app, you need:
# .env.production (set in Vercel dashboard)NEXT_PUBLIC_API_BASE=https://api.1pride.appFrom the API:
DATABASE_URL=postgresql+psycopg://user:pass@ep-x.neon.tech:5432/onepride?sslmode=requireCustom domains:
- Vercel project → Settings → Domains — add
1pride.appandapp.1pride.app. - DNS at your registrar — Vercel shows the exact records.
- For the API — a
CNAME api.1pride.app → fly.dev hostname, then add the cert in Fly.
Lions example
Concrete vercel.json for the app already lives at app/vercel.json —
nothing to add. The first deploy:
cd appnpx vercel # previewnpx vercel --prod # productionFor the API, a one-time Fly setup:
cd datafly launch # creates fly.toml, no DB pleasefly secrets set DATABASE_URL='postgresql+psycopg://...neon.tech/onepride?sslmode=require'fly deployFly auto-detects a Python app from pyproject.toml. The Procfile (or
fly.toml processes block) needs the uvicorn command:
web: uvicorn onepride_data.api:app --host 0.0.0.0 --port 8080Then fly certs add api.1pride.app after pointing DNS.
Try it
Don’t try the live deploy here — it’s coupled to your domain purchase. Instead, sketch the rollout checklist for going live:
- Buy
1pride.app. - Create Neon project, copy
DATABASE_URL. - Run the loader once against Neon:
DATABASE_URL=... uv run python -m onepride_data.load --years 2021-2024 --tables all. vercel --prodfromsite/and fromapp/.fly launch+fly deployfromdata/.- Point DNS for
1pride.app,app.1pride.app,api.1pride.app. - Set
NEXT_PUBLIC_API_BASE=https://api.1pride.appin Vercel’s app project. - Re-deploy the app (Vercel picks up new env vars).
The whole rollout from “have a clean repo” to “live URL” is under an hour if you’ve done it before, ~2 hours the first time.
Common mistakes
- DB on Vercel. Vercel doesn’t host Postgres. Use Neon, Supabase, Render, or a managed RDS.
localhostURLs in prod env vars. ReplaceNEXT_PUBLIC_API_BASEwhen promoting to prod or the app calls 127.0.0.1 from a browser. Funny error to debug at 11pm.- Forgetting
sslmode=requireon managed Postgres. Neon enforces it; the connection refuses without it. - Hot-reloading uvicorn in prod.
--reloadwatches files. Production doesn’t have files to watch. Drop the flag.
Quick check
- Why doesn’t Vercel host the FastAPI service or the Postgres DB?
- What env var connects the Next.js app to the API in production?
- What’s the difference between a Vercel preview deploy and a prod deploy?