logo
Back to Blog
CursorAIDeploymentDebuggingProductionEnvironment Variables

Cursor App Works Locally But Not in Production? Here's the Fix.

Convergex AIJuly 14, 20268 min read
A developer looking frustrated at a laptop screen with code, symbolizing a Cursor app failing in production.

It's a common headache: your Cursor app runs perfectly on localhost:3000 but breaks when deployed. We'll diagnose and fix hardcoded URLs, missing environment variables, and SQLite-to-Postgres migration issues.

You've just spent a few evenings with Cursor, crafting what feels like a genuinely innovative application. It runs beautifully on localhost:3000, the UI is slick, and the backend hums along. You're ready to share it with the world. Then, the inevitable happens: you deploy, and your Cursor app works locally but not in production. This isn't a unique problem; it's a rite of passage for many AI-generated apps that move from local sandbox to live server. The gap between 'working on my machine' and 'accessible via a URL' is often wider than expected, leading to frustration and wasted time.

At Convergex AI, we regularly see these issues with 'vibe coded' applications. The good news is that most of these deployment pitfalls are predictable and fixable. This hands-on guide will walk you through the most common reasons your Cursor app works locally but not in production, providing concrete steps to get your AI-generated creation running reliably.

The Local-to-Production Chasm

When your Cursor app runs locally, your laptop is a benevolent dictator, handling everything from the server runtime and file system to the database and environment variables (Source 4). It's a controlled, often permissive environment. Production, however, is a different beast. It's a remote server with a stricter configuration, different network access, and an expectation of robustness that local development simply doesn't enforce. The core challenge is that AI coding assistants like Cursor excel at generating functional code but don't inherently solve the infrastructure problem (Source 4).

Why Your Cursor App Works Locally But Not in Production

This discrepancy typically boils down to a few key areas:

  • Hardcoded Localhost URLs: Your AI assistant often assumes local endpoints for APIs, authentication callbacks, or asset paths.
  • Missing Environment Configuration: Production servers don't read your .env files. Secrets, API keys, and dynamic configurations need explicit setup.
  • Database Mismatch: SQLite, common for local development, is rarely suitable for production, necessitating a migration to something like PostgreSQL.

Let's tackle these head-on.

Hardcoded Localhost URLs: The Silent Killer

One of the most insidious issues is when your AI-generated code assumes localhost:3000 for various internal or external communication. This is particularly common in Next.js apps with API routes, OAuth callback URLs, or even image asset paths. When deployed, these localhost references break, often silently, leading to broken authentication flows, failed API calls, or missing content.

Finding and Fixing Localhost References

Your first step is to audit your codebase for any literal http://localhost strings. A simple grep or IDE search can reveal these quickly. For example, if you're using Supabase Auth with magic links, the callback URL might be set to localhost in your .env file or directly in the code (Source 1).

The Fix: Replace all hardcoded URLs with environment variables. This ensures your app dynamically adjusts its endpoints based on the deployment environment.

// Before (bad)
const SUPABASE_REDIRECT_URL = 'http://localhost:3000/auth/callback';

// After (good)
const SUPABASE_REDIRECT_URL = process.env.NEXT_PUBLIC_SUPABASE_REDIRECT_URL || 'http://localhost:3000/auth/callback';

Ensure that any variables needed on the client-side (like SUPABASE_REDIRECT_URL for a frontend redirect) are prefixed with NEXT_PUBLIC_ in Next.js (Source 5). Then, configure this variable in your production environment to point to your actual domain (e.g., https://your-app.com/auth/callback).

This is arguably the most frequent culprit when a Cursor app works locally but not in production. While Cursor efficiently uses .env files for local execution, these files are never deployed to your production server (Source 3, 5). Your production environment needs every secret, API key, and dynamic URL explicitly configured.

Auditing Your App's Dependencies

The first step is a thorough audit. Search your entire codebase for every instance of process.env (Source 3). List them out, categorizing them as:

  • Public (Client-side): Requires NEXT_PUBLIC_ prefix in Next.js. Available at build time and in the browser.
  • Private (Server-side): Only available on the server. Can be accessed at runtime.
  • Build-time vs. Runtime: Some variables are needed when your app is built, others only when it runs.

Pay close attention to database connection strings (DATABASE_URL), API keys (STRIPE_SECRET_KEY), authentication secrets (AUTH_SECRET), and any third-party service credentials (Source 3).

Configuring Variables on Your Deploy Platform

Once you have your comprehensive list, you must add each variable to your deployment platform's environment store. Platforms like Vercel and Railway provide dedicated sections for this (Source 5).

Example for Vercel/Railway:

  1. Navigate to your project settings.
  2. Find the 'Environment Variables' or 'Variables' tab.
  3. Add each variable name and its corresponding production value.
    • DATABASE_URL: postgresql://user:password@host:port/database
    • NEXT_PUBLIC_SUPABASE_URL: https://your-project.supabase.co
    • SUPABASE_SERVICE_ROLE_KEY: your_service_role_key (server-side only)

Crucial Note: Environment variables typically only apply to new deployments. After adding them, trigger a fresh deployment to ensure your changes take effect (Source 5).

SQLite vs. PostgreSQL: The Database Mismatch

For local development, Cursor often defaults to SQLite for its simplicity and file-based nature. It's fast to set up and requires no external services. However, SQLite is generally unsuitable for production web applications due to concurrency limitations and lack of robust features (Source 1, 2). Production demands a proper relational database like PostgreSQL.

Migrating Your Prisma Setup

If your Cursor app uses Prisma (a common choice for AI-generated apps), migrating from SQLite to PostgreSQL is relatively straightforward but requires attention to detail.

  1. Provision a PostgreSQL Database: Set up a managed PostgreSQL database. Services like Supabase, Railway's PostgreSQL, or Neon are excellent choices (Source 1, 4).

  2. Update schema.prisma: Change your datasource block to use postgresql and reference an environment variable for the connection URL.

    // Before (SQLite)
    datasource db {
      provider = "sqlite"
      url      = "file:./dev.db"
    }
    
    // After (PostgreSQL)
    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
    }
    
  3. Set DATABASE_URL: This is a critical environment variable. In your production environment, DATABASE_URL must contain the connection string to your newly provisioned PostgreSQL database.

    DATABASE_URL="postgresql://user:password@host:port/database?schema=public"
    
  4. Deploy Migrations: For Prisma, you'll need to apply your database migrations to the production PostgreSQL instance. Many deployment platforms integrate this into the build process. If not, you might need a custom build command:

    npx prisma migrate deploy
    

    This command applies all pending migrations defined in your prisma/migrations folder to the target database. Without this, your database schema in production will be empty, leading to runtime errors.

Verifying Your Fixes in a Real Environment

Making changes is only half the battle; verifying them is crucial. Don't just deploy and hope. Adopt a systematic approach to debugging when your Cursor app works locally but not in production.

The Critical Local Build Check

Before pushing anything to production, always run your build command locally. For most JavaScript projects, this is npm run build or yarn build (Source 6). If it fails locally, it will definitely fail in production. This catches TypeScript errors, missing dependencies, and some environment variable issues early.

# For Next.js projects
npm run build

# Or for other projects
yarn build

Leveraging Deployment Logs and Monitoring

Deployment logs are your best friend. Vercel, Railway, and similar platforms provide detailed logs for your build and runtime processes (Source 5). Look for error messages, stack traces (e.g., ERR-219), or warnings that indicate misconfigurations, missing files, or failed database connections. These logs often contain the exact clues you need to pinpoint the problem.

Once deployed, use your browser's developer tools to inspect network requests and console errors. For backend issues, ensure your server-side logs are accessible and actively monitored. Tools like Sentry or LogRocket can provide invaluable insights into runtime errors that might not appear in standard deployment logs.

If you find yourself constantly battling these deployment issues, remember that you're not alone. Many developers struggle with the transition from AI-generated prototype to production-ready product. For a deeper dive into common Cursor issues, check out our guide on how to fix Cursor apps.

Final Thoughts

Getting your Cursor app to work locally but not in production is a common hurdle, but it's one you can overcome with a methodical approach. By addressing hardcoded URLs, correctly configuring environment variables, and ensuring your database setup is production-ready, you transform your AI-generated prototype into a robust, deployable application. This process is part of refining the initial 'vibe code' into something truly production-grade.

If these challenges feel overwhelming or you need expert help turning your AI-generated prototype into a reliable, production-ready product, Convergex AI specializes in finishing vibe-coded apps. We'll handle the complexities so you can focus on innovation.

Related articles

Stuck at 80% on a vibe-coded app?

We finish, harden, and ship AI-generated apps. Let's talk.

Book a 15 min intro call