Deploy to Netlify

Deploy Frontend and Backend to Netlify

Use two Netlify sites from the same repo: one for the Next.js frontend, one for the Express API (serverless function).


Overview

| Site | Base directory | Build | Result | |------|----------------|--------|--------| | Frontend | frontend | Next.js (npm run build) | App at https://YOUR-FRONTEND-SITE.netlify.app | | Backend | backend | Prisma + TypeScript → Netlify Function | API at https://YOUR-BACKEND-SITE.netlify.app |

The frontend must know the backend URL via NEXT_PUBLIC_API_URL. Set it on the frontend site after the backend is deployed.


1. Deploy the backend (API) first

  1. In Netlify: Add new siteImport an existing project.
  2. Connect the uniph.ai repo.
  3. Build settings:
    • Base directory: backend
    • Build command: (leave default; uses backend/netlify.toml: npx prisma generate && npm run build)
    • Publish directory: leave empty (this site only serves the function)
  4. Environment variables (Site settings → Environment variables):
    • DATABASE_URL = your production PostgreSQL connection string (required).
      Use a hosted Postgres (e.g. Neon, Supabase); see backend/docs/NEON_SETUP.md if needed.
    • NODE_VERSION = 20 (optional; already in backend/netlify.toml)
  5. Run migrations against that database once (e.g. locally):
    cd backend && DATABASE_URL="postgresql://..." npx prisma migrate deploy
    
    Or use npx prisma db push if you're not using migrations yet.
  6. Deploy. Note the backend site URL, e.g. https://uniph-api.netlify.app (no trailing slash).

Check: Open https://YOUR-BACKEND-SITE.netlify.app/api/health. You should see {"ok":true,"db_configured":true,...}. If db_configured is false, set DATABASE_URL on the backend site and redeploy.


2. Deploy the frontend

  1. In Netlify: Add new siteImport an existing project (same repo).
  2. Build settings:
    • Base directory: frontend
    • Build command: (default from frontend/netlify.toml: npm run build)
    • Publish directory: (default; Next.js plugin uses .next)
  3. Environment variables (Site settings → Environment variables):
    • NEXT_PUBLIC_API_URL = https://YOUR-BACKEND-SITE.netlify.app (the backend URL from step 1; no trailing slash).
    • AUTH_SECRET = a random secret (e.g. openssl rand -base64 32).
    • NEXTAUTH_URL = https://YOUR-FRONTEND-SITE.netlify.app (this site's URL; set after first deploy or use a custom domain).
    • For OAuth: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET and/or MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET (and in the OAuth provider console, add this site's URL as redirect/callback).
  4. Deploy. After the first deploy, set NEXTAUTH_URL to the real site URL if you didn't already, then trigger a new deploy so it's baked in.

Check: Open the frontend URL, go to /auth, and sign in. Then open the dashboard; it should call the backend and show data (or empty state if no data yet).


3. Summary checklist

| Where | Variable | Value | |-------|----------|--------| | Backend site | DATABASE_URL | Production Postgres URL | | Frontend site | NEXT_PUBLIC_API_URL | Backend Netlify URL (e.g. https://uniph-api.netlify.app) | | Frontend site | AUTH_SECRET | Random secret | | Frontend site | NEXTAUTH_URL | Frontend Netlify URL (e.g. https://uniph.netlify.app) | | Frontend site (optional) | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | For Google sign-in | | Frontend site (optional) | MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET | For Microsoft sign-in |


4. Troubleshooting

  • Frontend shows "Unable to connect to the API"
    Set NEXT_PUBLIC_API_URL on the frontend site to the backend URL, then trigger a new deploy (build-time variable).

  • Backend /api/health shows db_configured: false
    Set DATABASE_URL on the backend site and redeploy.

  • Auth redirect or 500
    Ensure NEXTAUTH_URL matches the frontend URL (or custom domain) and that the OAuth app (Google/Microsoft) has the correct callback URL (e.g. https://YOUR-FRONTEND-SITE.netlify.app/api/auth/callback/google).

  • Build fails

    • Frontend: ensure Base directory is frontend and Node 20 (see frontend/netlify.toml).
    • Backend: ensure Base directory is backend; check build log for Prisma/TS errors.

5. Post-deploy smoke check (release gates)

From the repo root you can run a health check against the deployed backend (e.g. in CI or after deploy):

BACKEND_URL=https://YOUR-BACKEND-SITE.netlify.app npm run pre-deploy-check

To require that the database is configured (fail if db_configured is false):

BACKEND_URL=https://... REQUIRE_DB=1 npm run pre-deploy-check

See scripts/pre-deploy-check.mjs and roadmap Phase C (Release Reliability Gates).

To run the same check in CI: add BACKEND_URL to repo Secrets, then run the Smoke check (backend) workflow from the Actions tab (see .github/workflows/smoke-check.yml). For rollback steps, see Rollback playbook.


More detail:

  • Backend: backend/DEPLOY_NETLIFY.md and backend/docs/NETLIFY_TROUBLESHOOTING.md
  • Frontend: frontend/DEPLOYMENT.md and this app's Netlify Troubleshooting doc.