Skip to content

Configure production .env on Vercel for v1.0 ship #3

@abdout

Description

@abdout

Configure production env on Vercel for mkan v1.0

This issue tracks the env vars that need to be set on Vercel Production (and optionally Preview) before / after merging PR #2.

src/lib/env.ts validates these at first runtime call, so a missing required var fails fast with a readable error. Optional vars degrade gracefully (Stripe key absent → only Stripe paths fail; cash + cron flows still work).


Required (build & runtime)

Key What it does Where to get it
DATABASE_URL Neon PostgreSQL connection string. Neon dashboard → project → Connection string (pooled, with ?sslmode=require).
AUTH_SECRET NextAuth v5 JWT signing secret. ≥ 32 bytes. Generate with openssl rand -base64 32.
NEXTAUTH_URL Public origin for callback URLs. https://mkan.databayt.org (or your prod domain).
IMAGEKIT_PRIVATE_KEY ImageKit server-side uploads + DELETE. ImageKit dashboard → Developer → API keys.
NEXT_PUBLIC_IMAGEKIT_PUBLIC_KEY Client-side ImageKit upload init. Same dashboard.
NEXT_PUBLIC_IMAGEKIT_URL_ENDPOINT CDN base for transforms. https://ik.imagekit.io/<your-id>.
RESEND_API_KEY Transactional email (verify, 2FA, booking confirmation, trip cancelled). Resend dashboard → API Keys → Create.
EMAIL_FROM Sender address. Must match a verified domain in Resend. e.g. noreply@mkan.databayt.org.
UPSTASH_REDIS_REST_URL Rate limiting (auth/upload/search/payment/general tiers). Upstash console → database → REST URL.
UPSTASH_REDIS_REST_TOKEN Same. Upstash console → database → REST Token.

Recommended (live features depend on these)

Key What breaks without it Where to get it
STRIPE_SECRET_KEY Card payments via Stripe (homes lease + transport). Use live key for prod, test for preview. Stripe dashboard → Developers → API keys → Secret key.
STRIPE_WEBHOOK_SECRET Webhook signature verification at /api/webhooks/stripe. Without it, webhook returns 400. Stripe → Developers → Webhooks → Add endpoint https://<domain>/api/webhooks/stripe, copy the signing secret.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY Client-side Stripe.js for the card form. Stripe dashboard → publishable key.
NEXT_PUBLIC_MAPBOX_TOKEN Listing detail interactive map. (We fall back to OpenStreetMap iframe if absent.) Mapbox account → Access tokens.

Optional (auth providers + features)

Key Effect if missing
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET Google OAuth login button hides / errors. Credentials login still works.
FACEBOOK_CLIENT_ID / FACEBOOK_CLIENT_SECRET Same for Facebook.
GITHUB_PERSONAL_ACCESS_TOKEN / GITHUB_REPO Report-issue feature can't auto-file to GitHub.
CRON_SECRET /api/cron/{release-seats,mark-overdue,generate-monthly} accept calls without a secret check. Vercel cron sends a header you can validate. Recommended in prod.
NEXT_PUBLIC_APP_URL Defaults to http://localhost:3000. Set to prod domain so emails link correctly.

How to set them on Vercel

  1. Open the project on Vercel → Settings → Environment Variables.
  2. Add each key. Tick Production (and optionally Preview).
  3. Redeploy the latest production deployment so the new env is picked up (Vercel doesn't apply env changes to existing builds — only new ones).
# Or via CLI (requires `vercel link` + login):
vercel env add DATABASE_URL production
vercel env add AUTH_SECRET production
# ...
vercel --prod   # trigger fresh deploy

Verification checklist (after setting)

  • https://<domain>/api/health returns 200 with valid JSON.
  • https://<domain>/en/listings and /ar/listings render.
  • https://<domain>/en/transport and /ar/transport render.
  • Login via credentials succeeds (verify email, then sign in).
  • A test card payment succeeds end-to-end with Stripe test keys (preview env).
  • Webhook at /api/webhooks/stripe receives a payment_intent.succeeded event from Stripe CLI / Dashboard test trigger and returns 200.

Stripe webhook setup (gotcha)

The webhook endpoint must be added to Stripe after the prod URL is reachable:

  1. Deploy to Vercel first (without STRIPE_WEBHOOK_SECRET is fine — endpoint will 400 until it's set, but won't crash).
  2. In Stripe → Webhooks → Add endpoint → URL = https://<domain>/api/webhooks/stripe.
  3. Select events: payment_intent.succeeded, payment_intent.payment_failed, charge.refunded.
  4. Copy the new endpoint's signing secret.
  5. Set it as STRIPE_WEBHOOK_SECRET in Vercel.
  6. Redeploy.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requestedreportUser-reported issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions