Skip to content

Deployment Issues

If the template works locally but breaks after deploy, the problem is usually not “Nuxt does not work in production”. It is usually one of these:

  • the deployed env differs from local
  • the public domain and auth domain are misaligned
  • passkey RP ID still points at localhost
  • the server has too little memory for stable build or runtime behavior

Problem: Production Boots Differently Than Local

Section titled “Problem: Production Boots Differently Than Local”

This is common when .env.example placeholders were copied into the deployed environment without being cleaned up.

Examples:

  • fake Stripe key enables real Stripe code paths
  • fake OpenAI key enables real OpenAI code paths
  • production mail driver is set to resend, but the API key is missing

Do not compare only the files in Git. Compare the real deployed environment variables value by value.

Problem: The App Starts In Production, So You Assume The Deployment Is Fine

Section titled “Problem: The App Starts In Production, So You Assume The Deployment Is Fine”

That is not a safe conclusion in this template.

Startup env validation catches some shape errors, but it does not prove:

  • Stripe is usable
  • AI requests will succeed
  • SMTP or Resend can actually deliver mail
  • passkeys are bound to the correct relying party

Treat deploy validation as a feature-by-feature smoke test, not just a boot test.

Section titled “Problem: Auth, OAuth, Or Email Links Point To The Wrong Domain”

Your deployed public URLs must agree with each other.

Minimum checks:

  • NUXT_PUBLIC_SITE_URL
  • BETTER_AUTH_URL
  • OAuth callback registrations in provider consoles
  • Stripe success/cancel return URLs if you override them

If the app mixes localhost, preview domains, IP addresses, and the final production domain, you can get broken cookies, wrong callback redirects, or invalid verification links.

This is usually a relying-party problem.

If BETTER_AUTH_PASSKEY_RP_ID is still set to localhost, the explicit RP ID overrides automatic hostname resolution and production passkey flows can fail.

  1. set BETTER_AUTH_URL and NUXT_PUBLIC_SITE_URL to the real production origin
  2. set BETTER_AUTH_PASSKEY_RP_ID to the real hostname, or remove it entirely
  3. redeploy and test passkey registration again on the final domain

Problem: Coolify Build Or Runtime Feels Unstable

Section titled “Problem: Coolify Build Or Runtime Feels Unstable”

Based on your prior deployment test, treat 3.5 GB memory as the safer floor for Coolify.

Below that, you are more likely to see:

  • builds getting killed
  • unstable runtime behavior under load
  • provider-heavy flows failing in ways that are hard to reproduce locally

Problem: Billing Works Locally But Not After Deploy

Section titled “Problem: Billing Works Locally But Not After Deploy”

Production billing usually fails because one of these is wrong:

  • real Stripe secret key missing or invalid
  • webhook secret not aligned with the production endpoint
  • production price IDs missing
  • webhook endpoint not reachable from Stripe

Debug in this order:

  1. create one checkout session
  2. confirm checkout completes in Stripe
  3. confirm the webhook fires
  4. confirm local subscription state updates

Before blaming the deployment platform, verify the site the same way this repo expects:

Terminal window
pnpm typecheck
pnpm build

If the issue is route or rendering related, validate the built output with preview as well:

Terminal window
pnpm preview

Do not treat the development server as the final source of truth for deployed behavior.