Dependencies, Packages and Why Builds Break Elsewhere
A dependency is code you didn't write that your app relies on anyway. What package.json and a lockfile actually do, and why a build can fail the moment it leaves preview.
Quick answer
A dependency, or package, is code someone else wrote that your app relies on without you having to write it yourself, everything from a date-formatting library to a full UI component set. Lovable, Bolt.new and Base44 all track dependencies in a package.json file, and a lockfile alongside it records the exact versions actually installed, not just the ranges requested. Most of the time this stays invisible; it becomes visible the moment two packages want conflicting versions of something they both depend on, or the moment a fresh install (your builder's preview, a deploy to a different host, a teammate cloning the repo) doesn't reproduce exactly what worked before.
Tools for this build
The one-sentence version: code you didn't write, that your app relies on anyway
Almost nothing you build starts from a completely blank slate. Instead of writing your own date-formatting logic, your own component library, your own payment SDK, your AI agent adds a package, someone else's already-written, already-tested code, and your app uses it directly. This is the normal, efficient way modern software gets built, not a shortcut or a compromise. Our guide to the folder structure of an AI-built app already names the file where your project's list of packages lives, package.json; this page covers what actually goes wrong around that file and why.
Where dependencies actually live: package.json and the lockfile
package.json lists every package your project depends on, along with an acceptable version range for each. Alongside it sits a lockfile, package-lock.json or an equivalent depending on the specific tool, which records the exact version of every one of those packages, and every package those packages themselves depend on, that was actually installed the last time everything worked. The distinction matters: package.json says "a version like this is fine," the lockfile says "this exact version, precisely, is what actually ran."
package.json vs. the lockfile
package.json
An acceptable version range:
"Something compatible with this" for each dependency
The lockfile
The exact version actually installed:
Precisely what ran last time, down to every indirect dependency
AI Build · aibuild.co.za
Why adding one package can silently break another
Packages depend on other packages, often several layers deep, and two packages you add separately can each expect a different, incompatible version of something they both rely on underneath. This isn't a mistake in the code your AI agent wrote, it's a genuine, occasionally unavoidable consequence of how a real dependency tree works: hundreds of packages can sit behind the handful you explicitly asked for. When something breaks right after adding a new package, describing exactly what changed and what broke, the same discipline this site's own guide to describing a bug so your AI agent can actually fix it covers, gets to the actual conflict faster than a vague "it's broken now."
The lockfile: why "it worked a minute ago" sometimes means a different install happened
A fresh install, your builder's own preview refreshing, a deploy to a separate host, a teammate cloning a connected GitHub repository, reads package.json's version ranges and installs whatever currently satisfies them. Without a respected lockfile, that install can quietly pick up a newer version than the one your app was actually built and tested against, even though nothing in your own code changed at all. The lockfile exists specifically to stop this: as long as it's present and respected, every fresh install reproduces the exact same versions, not just "something compatible."
Why this shows up most clearly once you deploy somewhere else
Your builder's own preview and a separate deploy target can each run their own install, and if that install doesn't reproduce the same dependency versions, "works in preview, breaks once deployed" is exactly what results. A version mismatch can break the build itself, which can leave the live site blank. Our guide to a blank screen after deploying covers the four settings to rule out first, a missing environment variable and a wrong publish folder among them, and what the build log shows when the build itself failed; the guide to environment variables not working after deploy covers the first of those in more depth.
Not every platform exposes this the same way
Lovable and Bolt.new both generate a standard package.json your AI agent edits directly through your prompts, visible and readable the way any other project file is. Base44 also produces a standard React project with its own package.json, but manages more of the routine dependency handling behind its own interface, exposing less of the raw mechanics day to day than Lovable or Bolt.new do. Either way, you rarely need to read or edit the file yourself; describing what you need is enough for your AI agent to add the right package correctly.
Where to go next
- Where
package.jsonlives in a real generated project: React Folder Structure Explained for AI-Built Apps. - When a deploy shows a blank screen, the four settings to rule out before blaming a package: Blank Screen After Deploying? 4 Causes on Netlify or Any Host.
- The other thing "works in preview, breaks on deploy" is usually caused by: Environment Variables Not Working After Deploy.
Not affiliated with the platforms we write about
AI Build South Africa is an independent resource. We're not endorsed by, or an official partner of, PayFast, Yoco, Peach Payments, Ozow, Meta, Lovable, Base44, Bolt.new or Anthropic. We do participate in affiliate and referral programmes with some of these providers, including Base44. See our Disclaimer for the full disclosure and our Terms of Service for the wider terms.
Frequently asked questions
What is a dependency or package, in plain terms?
A piece of code someone else wrote that your app uses without you having to write it yourself, a date-formatting library, a UI component set, a payment SDK. Your AI agent adds one the moment your app needs to do something that library already handles well, rather than writing that functionality from scratch every time.
Why did my AI agent adding one package break something else?
Two packages can quietly expect different, incompatible versions of a third package they both depend on, a version conflict that only surfaces once both are actually installed together. This isn't a sign your AI agent made a mistake in the code it wrote, it's a real, occasionally unavoidable side effect of how packages depend on each other, and it's usually fixable by adjusting which specific version gets installed.
What is a lockfile, and why does it matter?
A lockfile (package-lock.json, bun.lock, or similar depending on the tool) records the exact version of every dependency, including the dependencies of your dependencies, that was actually installed the last time it worked. Without it, a fresh install can quietly pick up newer versions than the ones your app was actually built and tested against, which is exactly the gap behind "it worked a minute ago."
Why does my app work in my builder's preview but fail once deployed to Netlify?
Your builder's preview and a separate host like Netlify can each run their own fresh install of your dependencies, and if the lockfile isn't respected or is out of sync, that install doesn't have to produce identical results in both places. This is one of the concrete causes behind this site's own guide to a Netlify blank-screen deploy on a Bolt.new build, alongside missing environment variables and a wrong publish path.
Do Lovable, Base44 and Bolt.new all handle dependencies the same way?
Lovable and Bolt.new both generate a standard package.json your AI agent edits through prompts, the same file this site's own guide to a generated project's structure identifies as the dependency list. Base44 also produces a standard React project with its own package.json, but manages more of the day-to-day dependency handling behind its own interface, exposing less of the raw file directly than Lovable or Bolt.new do.
Should I ever edit package.json myself?
You don't need to for most real work; describing what you want to your AI agent, "add a library for formatting dates," is enough for it to add the right package and update the file correctly. Reading the file becomes useful once you're trying to understand exactly what your project depends on, not before.
Related reading
- Git and GitHub Basics for AI-Built Projects: the lockfile is exactly the kind of file a real commit history keeps consistent across machines.
- Why Your Vibe-Coded App Isn't Production-Ready Yet: the wider set of gaps between "it runs in preview" and "it's ready for real users".
- When Does Your App Actually Need a Real Database?: the same "connect it, then confirm it's actually set up right" discipline, applied to data instead of code.