Course:Node.js & Express/
Lesson

Every Node.js project you encounter, whether AI-generated or hand-written, starts with a package.json file. It is the blueprint of the project. When AI scaffolds a project for you, it creates this file, fills in dependencies, and writes npm scripts. Knowing how to read and evaluate what AI puts in package.json is a fundamental skill, because AI makes mistakes here that can bloat your project, introduce security vulnerabilities, or break your builds.

What npm does

npm (Node Package Manager) does three things: it installs packages from the npm registryWhat is registry?A server that stores and distributes packages or container images - npm registry for JavaScript packages, Docker Hub for container images. (a massive online database of JavaScript packages), it manages which packages your project depends on, and it runs scripts you define in package.json.

# Install all dependencies listed in package.json
npm install

# Add a new dependency
npm install express

# Add a dev dependency
npm install --save-dev typescript

# Run a script defined in package.json
npm run build

# Shorthand for common scripts
npm start      # runs "start" script
npm test       # runs "test" script
CommandWhat it doesWhen to use it
npm installInstalls all deps from package.jsonAfter cloning a project, or after package.json changes
npm install <pkg>Adds a package to dependenciesWhen your app needs a library at runtime
npm install -D <pkg>Adds a package to devDependenciesTesting tools, linters, build tools
npm uninstall <pkg>Removes a packageWhen you no longer need a dependency
npm run <script>Executes a script from package.jsonBuilding, testing, starting dev servers
npm outdatedShows which packages have newer versionsPeriodic dependency maintenance
02

Anatomy of package.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it.

Here is a typical package.json with the fields you will see most often:

json
{
  "name": "my-api-server",
  "version": "1.0.0",
  "description": "REST API for the dashboard app",
  "main": "src/index.js",
  "type": "module",
  "scripts": {
    "start": "node src/index.js",
    "dev": "nodemon src/index.js",
    "build": "tsc",
    "test": "vitest"
  },
  "dependencies": {
    "express": "^4.18.2",
    "pg": "^8.11.3"
  },
  "devDependencies": {
    "nodemon": "^3.0.2",
    "typescript": "^5.3.3",
    "vitest": "^1.2.0"
  }
}

The key fields

name: The project name. Lowercase, no spaces. Must be unique if you publish to npm.

version: The current version, following semver (more on this below).

type: Either "module" (ES ModulesWhat is es modules?The official JavaScript module standard using import and export - enabled in Node.js via "type": "module" in package.json., import/export) or "commonjs" (the default, require/module.exports). This single field controls how Node.js interprets your .js files. We cover this in the next lesson.

scripts: Custom commands you run with npm run <name>. This is where you define how to start, build, test, and deploy your project. start and test are special, they do not need the run keyword.

dependencies: Packages your application needs to run in production. Express, database drivers, authenticationWhat is authentication?Verifying who a user is, typically through credentials like a password or token. libraries.

devDependencies: Packages needed only during development. Testing frameworks, TypeScript compilerWhat is compiler?A program that translates code you write into a language your computer can execute. It also catches errors before your code runs., linters, build tools.

AI pitfall
AI routinely puts devDependencies in dependencies and vice versa. TypeScript in dependencies instead of devDependencies means your production Docker image installs the TypeScript compiler even though the code is already compiled. A testing framework in dependencies adds unnecessary weight to production. Always review which section AI places packages in.
03

Semver: reading version numbers

Every package version follows semantic versioningWhat is semantic versioning?A numbering system (major.minor.patch) that communicates whether a release contains breaking changes, new features, or bug fixes.: MAJOR.MINOR.PATCH.

PartWhen it changesExample
MAJOR (4.x.x)Breaking changes, your code might break on updateExpress 3 to Express 4
MINOR (4.18.x)New features, backward-compatibleNew middleware added
PATCH (4.18.2)Bug fixes, backward-compatibleSecurity patch

The ^ and ~ prefixes in package.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it. control which updates npm installs automatically:

  • "^4.18.2", Allows minor and patch updates (4.18.2 through 4.x.x, but not 5.0.0)
  • "~4.18.2", Allows only patch updates (4.18.2 through 4.18.x)
  • "4.18.2", Exact version, no updates

The ^ prefix is the default when you run npm install. It is usually the right choice, you get bug fixes and new features without breaking changes. But "backward-compatible" is a promiseWhat is promise?An object that represents a value you don't have yet but will get in the future, letting your code keep running while it waits., and sometimes packages break it.

04

The lock file

package-lock.json records the exact version of every package that was installed, including all sub-dependencies. When you run npm install, npm uses the lock file to install the exact same versions every time.

package.json says:     "express": "^4.18.2"
package-lock.json says: "express": "4.18.3"  (the exact resolved version)

Always commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed. package-lock.json to git. Without it, two developers running npm install on the same project can get different package versions, leading to "it works on my machine" bugs.

FilePurposeCommit to git?
package.jsonDeclares dependency rangesYes
package-lock.jsonLocks exact versionsYes
node_modules/The actual installed packagesNo (add to .gitignore)
05

node_modules: the elephant in the room

When you run npm install, npm downloads every package and its dependencies into a node_modules folder. A modest project can easily have 500+ packages in node_modules, totaling hundreds of megabytes.

This is normal. You do not check node_modules into git, anyone who clones the project runs npm install to recreate it from package.json and the lock file.

AI pitfall
AI loves adding packages. Ask it to build a simple feature and it might install 5 npm packages when 1 (or zero) would suffice. Each package adds to your bundle size, increases your attack surface, and becomes a maintenance burden. Before accepting an AI-suggested npm install, ask: "Can I do this with what I already have?" Often, the answer is yes.
06

npm scripts in practice

Scripts are the command center of your project. Here are common patterns:

json
{
  "scripts": {
    "dev": "nodemon --watch src src/index.ts",
    "build": "tsc && node dist/index.js",
    "start": "node dist/index.js",
    "test": "vitest",
    "lint": "eslint src/",
    "prestart": "npm run build",
    "posttest": "npm run lint"
  }
}

The pre and post prefixes are special, prestart runs automatically before start, and posttest runs after test. This lets you chain operations without complex shell commands.

07

Evaluating AI-generated package.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it.

When AI generates a package.json for you, check these things:

  1. Are the packages current? AI training data has a cutoff. It might suggest Express 4 when Express 5 is available, or a package that has been deprecated.
  2. Are there unnecessary packages? If the project has lodash but only uses one function from it, that is bloat.
  3. Are dev dependencies separated correctly? Testing and build tools belong in devDependencies.
  4. Does the lock file exist? If AI generates a project without package-lock.json, run npm install to create one.
  5. Are the scripts reasonable? A dev script should use a file watcher. A build script should compile TypeScript if the project uses it.