Why Your AI-Generated Next.js App Fails to Build (and How to Fix Missing Imports Automatically) | Deployxa

Cursor and Lovable import clsx, lucide-react, and Radix without writing them to package.json. Here is why your Next.js build crashes in production and how Deployxa's AutoRepairService fixes it automatically.

← Back to Dispatch Articles
Engineering Log

Why Your AI-Generated Next.js App Fails to Build (and How to Fix Missing Imports Automatically)

Cursor and Lovable import clsx, lucide-react, and Radix without writing them to package.json. Here is why your Next.js build crashes in production and how Deployxa's AutoRepairService fixes it automatically.

Why Your AI-Generated Next.js App Fails to Build

You spent two hours prompting your dream micro-SaaS into existence inside Cursor. The UI looks gorgeous, the components snap into place, and npm run dev purrs like a kitten on your machine. You push to GitHub, connect your repo to a cloud provider, and hit deploy. Boom. Build Failed: Cannot find module 'clsx'. Cryptic lines about missing lucide-react, TypeScript strict errors, and connection refused on localhost:3000 follow. Your vibe is officially dead. Here is why this happens, why it is not your fault, and how to never let a missing import kill your momentum again.

The root cause is structural, not careless. LLMs predict the next token based on patterns in their training data, and clsx, lucide-react, @radix-ui/react-slot, tailwind-merge, and zod appear so frequently in modern React code that the model writes the import statement confidently without ever checking whether the package is actually listed in your package.json. Locally, this works because you probably installed it during a previous session, or because npm run dev resolves from a wider node_modules tree. In a fresh Docker build on a cloud provider, the only packages that exist are the ones declared in package.json and package-lock.json. Everything else is gone, and the compiler tells you so in the harshest possible way.

Why LLMs Forget UI Dependencies in package.json

The pattern is consistent across Cursor, Lovable, Bolt.new, and v0. The model writes clean, idiomatic React code that imports from popular libraries, but it treats the dependency manifest as an afterthought. Three reasons explain this. First, the LLM's training set is dominated by code where imports already work, so the conditional behavior of "add to package.json when importing a new package" is under-represented. Second, most coding assistants optimize for file-level changes, and package.json is often in a different file than the component being edited, so the agent never crosses that boundary unprompted. Third, the agent rarely runs the app in a clean environment during a session, so it never observes the failure mode and never learns to preempt it.

The result is a class of bugs that are invisible during local development and fatal during cloud deployment. The same code that won you a dopamine hit at 2 AM becomes a wall of red stderr at 9 AM. Worse, the error messages are often misleading. A missing clsx import surfaces as a TypeScript compilation error inside a deeply nested component, not as a friendly "please install clsx" prompt. You end up reading 800 lines of build log to discover that the entire failure was caused by a single missing package that should have been added hours ago.

There is a second-order effect worth naming. Most AI coding assistants in 2026 can be configured to run a post-edit lint or install step, but very few vibe coders ever turn that on. The default in Cursor, for example, is to write the file and stop. The agent will not silently run npm install clsx on your behalf unless you explicitly tell it to, because doing so without confirmation could introduce a package you did not want. The conservative default is correct from a security perspective, but it means the gap between "imported" and "installed" persists until the cloud build catches it. The fix is not to make the LLM smarter; the fix is to make the build platform tolerant of this known mismatch.

A useful mental model: think of package.json as a contract between your repository and any clean environment that tries to build it. The LLM writes code that violates the contract by referencing symbols the contract does not enumerate. Locally, your warm node_modules paper over the violation. Remotely, there is no warm node_modules, and the contract is enforced. AutoRepairService is the mechanism that reconciles the contract at build time without requiring you to do anything.

The Traditional 10-Step Manual Fix

Without auto-repair, recovering from this failure looks like a small ritual. You read the build log top to bottom, identify the first Cannot find module error, manually run npm install clsx, push the fix, trigger a new build, watch it fail on the next missing package, repeat. A typical AI-generated landing page can pull in five to ten UI helper packages, so you cycle through this loop multiple times. Then you hit the TypeScript strict errors that Next.js 15 enables by default, and you spend another hour editing next.config.js to bypass them. Then you discover the hardcoded localhost:3000 URLs in your client fetches, and you start a string-replace marathon across your codebase. Then you write a Dockerfile, configure environment variables, set up SSL, and bind ports. By the time the app is live, you have spent more time on DevOps than on the product itself.

Concretely, the manual recovery loop for a single missing package looks like this:

# 1. Read the failed build log on Vercel or Netlify
# 2. Spot the line: Module not found: Can't resolve 'clsx'
# 3. Locally:
npm install clsx
git add package.json package-lock.json
git commit -m "fix: add missing clsx dependency"
git push origin main
# 4. Wait 45-90 seconds for Vercel to rebuild
# 5. Watch it fail on the next missing package: 'lucide-react'
# 6. Repeat steps 3-5 until all imports resolve

For an app with seven missing packages, this loop consumes 20 to 40 minutes of human attention, plus 10 to 15 minutes of build time per failed attempt. Worse, the loop is psychologically corrosive: each iteration feels like progress, but the next failure erases it. By the fourth or fifth iteration, most vibe coders abandon the deployment and start second-guessing the entire project.

How Deployxa's AutoRepairService Injects Missing Packages at Build Time

Deployxa was built for exactly this moment. When your build fails, the AutoRepairService does not just show you the error and give up. It traps the compilation stderr, feeds it to a classifier powered by Gemini 2.5 Flash with a regex fallback, and identifies the specific missing packages by name. It then injects those packages into your package.json, cleans the lockfile, and retries the build automatically. Up to two retry attempts are attempted before the platform gives up and surfaces the error to you. In the majority of cases, the second build succeeds and your app goes live without you ever touching a terminal.

The dashboard shows you exactly what happened. A banner reads something like: "Build failed due to missing clsx and lucide-react. Auto-installed both packages and resumed deployment. Build succeeded on attempt 2." You see the diff, you see the patched package.json, and you can review the change before accepting it into your main branch. The repair is bounded, transparent, and reversible. It is not a magic black box that rewrites your code; it is a targeted injection of packages that the compiler itself identified as missing.

How the Classifier Decides What to Install

The classifier pipeline is deliberately simple, which is why it is reliable. When the build step emits stderr, Deployxa captures the full log and runs it through two layers in parallel. The first layer is Gemini 2.5 Flash, prompted with a tight contract: "Given the following build error output, return a JSON array of npm package names that are missing and need to be installed. Do not include version numbers. Do not include dev-only packages unless the error clearly indicates a dev dependency." The second layer is a regex sweep for the canonical Module not found: Can't resolve '(.+?)' and Cannot find module '(.+?)' patterns, plus the TypeScript variant TS2307: Cannot find module '(.+?)'. The two results are merged, deduped, and filtered against a small blocklist (packages known to be malicious, abandoned, or renamed). The merged list is then injected into package.json with a latest tag, and npm install is run in the build context to regenerate the lockfile.

The regex fallback exists for two reasons. First, Gemini is not deterministic, and on rare occasions it returns an empty array or hallucinates a package name that does not exist. The regex layer catches the obvious cases even when Gemini stumbles. Second, the regex layer is fast (under 50ms), so it runs first and short-circuits Gemini for trivially identifiable errors. Gemini is only invoked when the regex layer returns nothing, which keeps API costs predictable and latency low.

The retry budget is capped at two. The first retry handles the common case: a missing package that, once installed, lets the build complete. The second retry handles the cascading case: the first missing package masked a second missing package, which only surfaces once the first is installed. Beyond two retries, the failure is no longer "missing package" class, and the platform stops burning build minutes on it.

Step-by-Step: Deploying an AI-Generated Next.js App Without Manual Fixes

Here is the exact workflow that takes a Cursor-generated Next.js app from local prototype to live URL without you editing a single file.

Step 1: Push your project to GitHub

Your repository should look like a standard Next.js app. Deployxa does not require a Dockerfile, a deploy.json, or any configuration file you do not already have.

git init
git add .
git commit -m "initial cursor-generated next.js app"
git remote add origin https://github.com/yourname/your-app.git
git push -u origin main

Step 2: Connect the repo to Deployxa

Open the Deployxa dashboard, click New App, and select your GitHub repository. Deployxa auto-detects Next.js from your package.json and configures the build command (npm run build), start command (npm start), and port binding automatically. You do not write a Dockerfile.

Step 3: Add your environment variables

Add any secrets your app needs. For a typical Next.js app with Prisma, you would add DATABASE_URL. Deployxa's pre-flight scanner checks for known required variables and warns you before the build starts, so you do not waste a build cycle on a missing secret.

Step 4: Hit deploy and watch the auto-repair loop

The first build runs. If your AI assistant forgot to add clsx, lucide-react, or any other package to package.json, the build fails, the AutoRepairService kicks in, patches the manifest, and retries. You watch this happen in real time in the build log panel. The second build typically succeeds, and the app is live within 60 to 90 seconds of the first failure.

Step 5: Verify with deployxa doctor

Once the app is live, run deployxa doctor from the CLI or click the Readiness tab in the dashboard. You get a 14-point health check covering SSL, DNS, environment variables, health endpoints, container status, and more. A grade from A to F tells you exactly how production-ready the deployment is, in plain English.

npm i -g @deployxa/cli
deployxa login
deployxa doctor --app your-app-name

Step 6: Roll forward or roll back

If a future deployment introduces a regression, Deployxa's blue/green release system means the new version only takes traffic when it passes health checks. If it fails, traffic stays on the previous healthy release. You can roll back to any prior release with a single command, and the rollback is atomic.

Common Pitfalls

Even with auto-repair, a handful of edge cases trip up vibe coders. The first is private npm packages. If your code imports from a private registry (for example, @yourcompany/internal-ui), the AutoRepairService will detect the missing package and try to install it, but the install will fail because the build context has no credentials for your private registry. The fix is to configure an .npmrc file with an auth token in the Deployxa dashboard under Build Settings, which gets injected into the build context. The second pitfall is version mismatches. The repair service installs the latest version of a missing package, which may be a major version newer than what your code expects. If clsx v2 introduced a breaking change and your code uses v1 APIs, the build will succeed but the runtime will break. The fix is to pin the version in your package.json after the first successful deploy, then push again. The third pitfall is dev-only dependencies. If the missing package is a TypeScript type definition like @types/react-date-range, the classifier may flag it as a regular dependency instead of a devDependency. The build still succeeds, but the production bundle is slightly larger than it should be. Move it to devDependencies manually after the first deploy.

Troubleshooting: Real Error Messages and What They Mean

Below are the five most common build errors AutoRepairService handles, with the literal error string and the interpretation.

Error: Module not found: Can't resolve 'clsx'
  at compile (/app/node_modules/next/dist/build/webpack-config.js:...)

Meaning: webpack's resolver could not find clsx in node_modules. The AutoRepairService will add clsx to dependencies and retry.

Error: Cannot find module 'lucide-react' or its corresponding type declarations.
  ts(2307)

Meaning: TypeScript cannot resolve the module. The AutoRepairService will add lucide-react and, if needed, @types/lucide-react (though lucide-react ships its own types, so the second install is usually skipped).

Failed to compile.
./src/components/Button.tsx
Module not found: Can't resolve '@radix-ui/react-slot'

Meaning: a Radix primitive is missing. The AutoRepairService will install @radix-ui/react-slot. Note that Radix packages are scoped and versioned independently, so if your code also imports @radix-ui/react-dialog, that will surface as a second error and be handled on the second retry.

> next build
Error: Cannot find module 'tailwind-merge'

Meaning: a utility used by cn() helpers is missing. The AutoRepairService will install tailwind-merge.

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/utils' is not defined

Meaning: a package is installed, but the import path is wrong. The AutoRepairService will not handle this, because the package is present and the error is in your import path. The dashboard surfaces the raw error and points you to the package's exports map.

Pricing Reality: Build Minutes vs Auto-Repair Budget

The economics of auto-repair matter because every retry consumes build minutes. On Vercel's Hobby plan, build minutes are capped at 6,000 per month (roughly 100 minutes per day). A single AI-generated Next.js app with seven missing packages can burn through 15 to 25 build minutes on its first deploy if you are manually iterating. Multiply by five projects per month, and the hobby plan is exhausted. On Vercel Pro at $20 per user per month, you get 6,000 minutes plus $40 of usage-based overages at $40 per 1,000 minutes. A traffic spike plus a series of failed builds can push the bill past $60 in a single month.

Deployxa's pricing is flat by design. The free tier includes 3 active apps with 512MB RAM each, and auto-repair retries are not billed as separate build minutes. The paid tier at $9 per month covers 15 apps with the same auto-repair budget. There is no per-build-minute metering, because the platform's cost structure is based on provisioned container capacity (hardened Docker cgroups on AMD EPYC bare-metal hosts behind Cloudflare), not on transient build operations. This means a vibe coder iterating on 10 projects in a month pays $9 total, regardless of how many times the AutoRepairService retries.

Cost Comparison Table

| Scenario | Vercel Hobby | Vercel Pro | Deployxa Free | Deployxa Paid |

|---|---|---|---|---|

| 3 apps, light traffic | $0 | $20/mo | $0 | $9/mo |

| 15 apps, moderate traffic | Not supported (3 app limit) | $20 + overages | Not supported (3 app limit) | $9/mo |

| Failed builds due to missing packages | Counts against 6,000 min/mo | Counts against 6,000 min/mo + $40 overage budget | Not metered | Not metered |

| Auto-repair retries | N/A | N/A | Included | Included |

Common Pitfalls and Troubleshooting

Even with the AutoRepairService, there are edge cases worth knowing about. The first is private npm packages. If your project references packages from a private npm registry (e.g., @yourcompany/internal-lib), the AutoRepairService cannot install them because it does not have your registry credentials. The fix is to configure an .npmrc file with your registry authentication token as a build-time environment variable in the Deployxa dashboard. The second is peer dependency conflicts. Sometimes the AutoRepairService installs a package that has a peer dependency conflict with an existing package (e.g., installing react@18 when your project uses react@19). In these cases, the retry build fails with an ERESOLVE error, and the AutoRepairService surfaces the error for manual resolution. The fix is typically to install a compatible version of the conflicting package or to add an .npmrc file with legacy-peer-deps=true. The third is monorepo hoisting issues. If your project is a monorepo using npm workspaces or Yarn workspaces, the AutoRepairService might install a package in the wrong workspace. The fix is to ensure your workspace configuration is correct and to run npm install in the correct workspace directory. The fourth is cached lockfile mismatches. If your package-lock.json is out of sync with your package.json (e.g., you manually edited package.json without running npm install), the AutoRepairService might fail to update the lockfile correctly. The fix is to delete package-lock.json, push again, and let the platform regenerate it. Each of these edge cases is documented in the Deployxa docs with specific error messages and recommended fixes, so you can diagnose and resolve them quickly.

Performance and Cost Considerations

The AutoRepairService adds a small overhead to builds that fail and trigger a retry. A typical retry takes 30 to 60 seconds, depending on the number of missing packages and the size of your dependency tree. For builds that succeed on the first attempt, there is no overhead. The cost of the AutoRepairService is included in your Deployxa plan; there is no per-retry charge. For teams that push frequently (e.g., 20 pushes per day), the total overhead from retries is typically under 10 minutes per day, which is negligible compared to the time saved by not debugging missing dependencies manually. The Gemini 2.5 Flash API calls are batched and rate-limited to avoid excessive costs, and the regex fallback ensures the service keeps working even when the Gemini API is unavailable.

When Auto-Repair Is Not Enough

The AutoRepairService is bounded by design. It handles missing npm packages and lockfile corruption. It does not rewrite your application logic, fix syntax errors in your code, or patch breaking changes in major framework versions. If your build fails because you upgraded Next.js from 14 to 15 and a deprecated API was removed, the repair service will not invent a migration for you. In those cases, the dashboard surfaces the raw error with a clear explanation, and you take it from there. This is the honest boundary: Deployxa fixes the boring, repetitive failure modes that kill vibe coder momentum, and it leaves the genuinely creative debugging to you and your AI assistant.

When Deployxa Is Not the Right Choice

There are workloads where Deployxa is the wrong tool, and pretending otherwise would be dishonest. If you need multi-region active-active replication (users in Singapore and Frankfurt hitting local read replicas with sub-50ms latency), Deployxa is single-region by design, and you should look at Fly.io or a custom Kubernetes setup. If you need Firecracker microVM-level isolation for running untrusted tenant code (a multi-tenant SaaS where customers upload arbitrary Python), Deployxa's hardened Docker cgroups are not the right security boundary, and you should look at AWS Lambda with custom runtimes or a dedicated microVM platform. If you need GPU access for inference workloads, Deployxa does not provision GPUs, and you should use Modal, Replicate, or a raw GPU cloud. If you are running a regulated workload that requires SOC 2 Type II attestation for the compute layer specifically, Deployxa's compliance posture may not satisfy your auditor, and you should look at AWS, GCP, or Azure with their respective compliance packages.

None of these are failures of Deployxa; they are scope decisions. Deployxa is optimized for vibe coders shipping web apps, APIs, and dashboards to a global audience from a single region with Cloudflare in front. For that use case, the trade-offs are correct. For everything else, use the right tool.

Conclusion: Ship Without the Build Tax

The gap between "it works on my machine" and "it is live on the internet" should not be a multi-hour DevOps tax on every AI-generated project. Deployxa closes that gap by treating build failures as solvable problems rather than terminal states. The next time Cursor or Lovable hands you a beautiful app with a half-empty package.json, do not spend an hour hunting down missing imports. Push the repo, hit deploy, and let the AutoRepairService do the boring work.

Ready to ship without the build tax? Drag your project folder to Deployxa Drop for an instant live preview with zero signup, or install the CLI with npm i -g @deployxa/cli and deploy from your terminal. For a deeper comparison of how Deployxa stacks up against traditional platforms, see Deployxa vs Vercel, and explore the full free developer tools catalog to speed up your workflow.

Ready to deploy with Deployxa?

Deploy your apps globally with automatic SSL and AI diagnostics.

Start Free Now