Most setup issues come from missing env vars, mismatched domains, provider dashboards still using local values, or production services using test credentials. Start with the exact error message, then check the matching section below.
Missing Environment Variables
If the app fails at startup with a missing env var error, open .env.local and compare it with .env.example.
Common fixes:
- Keep
.env.localin the project root. - Restart
bun run devafter changing env vars. - Use production values only in production.
- Use local values only in local development.
- Keep public browser values prefixed with
NEXT_PUBLIC_.
Database Connection Fails
Check that DATABASE_URL and DIRECT_URL exist, point to the right environment, and use the correct database credentials. Restart the dev server after changing them.
The Database section covers the exact Neon URL setup, local database workflow, production workflow, and provider switching notes.
Google OAuth Redirect Mismatch
If Google shows redirect_uri_mismatch, the URL in Google Cloud Console does not match the app.
For local development, add:
http://localhost:3000
http://localhost:3000/api/auth/callback/googleFor production, add:
https://your-domain.com
https://your-domain.com/api/auth/callback/googleAlso confirm NEXT_PUBLIC_DOMAIN is correct for the environment.
Passkeys Do Not Work
Check BETTER_AUTH_PASSKEY_RP_ID.
Use this locally:
BETTER_AUTH_PASSKEY_RP_ID=localhostUse the bare domain in production:
BETTER_AUTH_PASSKEY_RP_ID=your-domain.comDo not include https:// in the relying party ID.
Stripe Checkout Does Not Open
Check:
STRIPE_SECRET_KEY.- Stripe Price IDs.
- The requested checkout product is allowed by the checkout schema.
- The server can fetch the Stripe Price object.
Use test keys with test prices, and live keys with live prices. Do not mix them.
Stripe Webhooks Do Not Update Access
For local development, keep the Stripe listener running.
bun stripe:listenCopy the whsec_... value printed by the Stripe CLI into .env.local.
STRIPE_WEBHOOK_SECRET="whsec_..."For production, add this endpoint in Stripe:
https://your-domain.com/api/auth/stripe/webhookThen copy the production webhook signing secret into production env vars.
Blob Uploads Fail
Check that you created both Blob stores.
BLOB_READ_WRITE_TOKENshould point to the private store for user files.BLOB_PUBLIC_READ_WRITE_TOKENshould point to the public store for blog covers and public assets.
If blog covers upload but private files fail, check the private token. If private files upload but public blog covers fail, check the public token.
Emails Are Not Sending
Check:
RESEND_API_KEY.RESEND_FROM_EMAIL.SUPPORT_EMAIL.- Resend domain verification.
In production, use a sender email from a verified domain. Some inboxes reject or spam emails from unverified senders.
Realtime Updates Do Not Appear
Check Pusher values.
PUSHER_APP_ID="..."
PUSHER_SECRET="..."
NEXT_PUBLIC_PUSHER_KEY="..."
NEXT_PUBLIC_PUSHER_CLUSTER="..."Make sure the key and cluster are from the same Pusher app. Restart the dev server after changing values.
Analytics Are Not Showing
Check:
NEXT_PUBLIC_ANALYTICS_TRACKING="on"
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN="phc_..."
NEXT_PUBLIC_POSTHOG_HOST="https://us.i.posthog.com"Use the PostHog host that matches your project region.
Lighthouse Says Meta Description Is Missing
Next.js 15.2 introduced streaming support for async generateMetadata. Some audit tools can inspect the initial response before streamed metadata is visible.
Before changing SEO code:
- Check rendered page source.
- Check the completed DOM.
- Check bot user agent behavior.
- Confirm metadata exists for HTML limited bots through
htmlLimitedBots.
The SEO docs explain this behavior in more detail.
Production Deploy Fails
Check the Vercel build logs first.
Common causes:
- Missing production env vars.
- Database setup mismatch.
- Wrong production database URLs.
- Provider keys copied from test mode into production.
- Database client setup did not finish before build.
NEXT_PUBLIC_DOMAINstill points to localhost.
Run local verification before redeploying.
bun run lint
bun run buildAdmin Page Is Not Visible
Create an account first, then promote the user in the database.
Set the role field on the User row to:
adminSign out and sign in again after changing the role.