Open package.json and count the lines. Now open pnpm-lock.yaml and count those. The second number is usually somewhere between three hundred and a thousand, and it is the real answer to "how much code is in my project".

You wrote almost none of it. You are responsible for all of it.

The idea

A is code you have agreed to run without reading. That is a good trade, because writing your own date library is a worse use of your life. The cost of the trade is that those packages keep changing: bugs get fixed, security holes get found and patched, and occasionally the authors decide to break something on purpose. Updating is how you stay on the version that has the fix. Not updating is a decision too, it just does not feel like one.

code
     4  .  2  .  7        the version number, three parts
     |     |     |
     |     |     +--  PATCH  bug and security fixes only
     |     |            4.2.7 -> 4.2.8   read the diff, ship it
     |     |
     |     +--------  MINOR  new features, your code still works
     |                  4.2.7 -> 4.3.0   usually safe, still test
     |
     +--------------  MAJOR  they removed or changed something
                        4.2.7 -> 5.0.0   read their upgrade guide first

How it works

That three-part scheme is called semantic versioning, and most of the JavaScript world follows it. It is a promise, not a guarantee. A patch release can still break you.

Security updates are the ones with a deadline. When a vulnerability is found in a package, it gets a public advisory with an identifier and a severity, and that publication tells attackers exactly what to look for. npm audit (or pnpm audit) reads your lockfile and lists any advisories affecting what you have installed. GitHub's Dependabot does the same thing continuously and opens a pull request with the fix already applied.

Severity is about the package, not about you. A high severity flaw in a build tool that never runs in production is less urgent than a moderate one in the library that parses incoming requests. Read what the advisory actually describes before you panic or before you ignore it.

What to do

  1. Turn on Dependabot security updates in your GitHub repository settings. It is two clicks and it is the only part of this that happens without you.
  2. Do patch and minor updates in a batch, on a schedule you can keep. Once a month is plenty for a small project. Run pnpm update, then run the app and click through the paths that matter.
  3. Do major upgrades one package at a time, in their own commit. Ask Claude Code to read the upgrade guide for that specific version jump, apply it, and explain each change. Then read the diff yourself. A migration an AI performed and you approved without reading is a change nobody has reviewed.

Where it breaks

Updates break working software. This is the honest tension: the safest version to run is the one you have tested, and the safest version to run is the one with the security fix, and those are different versions. Nobody resolves that for you. What makes it survivable is being able to undo, which means committing before you upgrade and never batching an upgrade with a feature.

Automated tools also over-report. Advisories fire on packages that only run during your build, on transitive dependencies you cannot upgrade directly, and on flaws that need conditions your app never creates. If you treat every alert as an emergency you will stop reading them within a month.

The opposite failure is slower and much worse. A project two years behind cannot take a security patch without also taking six major versions of everything, and at that point the upgrade is a rewrite.