package.json is the instruction manual for a project that uses npm. Once you can open and read it, even a project you’re seeing for the first time tells you “what parts it uses and what commands run it.” There are actually only three places to look—dependencies, scripts, and version notation.
First, the big picture
A small project’s package.json looks something like this, for example.
{
"name": "my-site",
"version": "1.0.0",
"scripts": {
"dev": "astro dev",
"build": "astro build"
},
"dependencies": {
"astro": "5.1.0"
},
"devDependencies": {
"prettier": "3.4.2"
}
}From the top: the project’s own name and version, the tasks you can run (scripts), and the list of needed parts (the dependencies family). npm install reads this file and fetches the parts.
dependencies—parts used in production too
dependencies is the list of parts the finished site or app needs to run. When you add a part with npm install <name>, it’s automatically appended here.
devDependencies are tools used only during development work. Things that aren’t part of the finished product—like prettier for tidily formatting code, or testing tools—go here (appended with npm install -D <name>).
While you’re a beginner, you don’t need to memorize this distinction strictly. Just grasp that “the dependencies family = the list of parts that npm install brings in,” and follow the tutorial’s instructions for where to put them.
scripts—this project’s “task menu”
scripts is a menu that gives short names to commands you use often. You run them with npm run <name>.
"scripts": {
"dev": "astro dev", // npm run dev → start the dev server
"build": "astro build" // npm run build → generate files for publishing
}When a tutorial says “please run npm run dev,” what actually runs is the command written on the right side. When you touch an unfamiliar project, look at scripts first—that alone gives you a sense of “what this project can do.”
Version notation—know what ”^” means
A version like "astro": "5.1.0" can also be written with symbols attached.
| Notation | Meaning |
|---|---|
5.1.0 | Install exactly this version only |
^5.1.0 | You may install the latest within the 5.x.x range (below 6.0.0) |
~5.1.0 | You may install the latest within the 5.1.x range |
>=5.1.0, *, latest | No upper limit, always the latest—notation where you can’t predict what gets installed |
^ (caret) is the notation automatically attached when you run npm install <name>—the de facto standard, so to speak. The upside is “you automatically get newer versions with bug fixes.” But flip it around and it also means the contents that get installed change depending on the day you install. This trait ties into security too, so we cover it in detail in the next article.
The last row’s >=, *, and latest are notations that set no upper limit, and they’re often avoided in practice. Viewed through the lens of “can I reproduce today’s exact contents tomorrow too?”, the meaning of version notation becomes easier to grasp.
package-lock.json—a record of “what actually got installed”
package-lock.json, which appears next to package.json, is an exact record of the precise versions of all parts that were actually installed. Think of it as the receipt for the shopping list (package.json).
- Don’t delete it, don’t edit it by hand—npm manages it automatically
- Put it in Git—with this receipt, the whole team and your future self can reproduce the exact same set of parts
Summary of this lesson
- package.json is the project’s instruction manual—the places to look are
dependencies(the parts list) andscripts(the task menu) - The truth behind
npm run devis written in the scripts section—with an unfamiliar project, read scripts first ^1.2.3is the mark for “you may install the latest within the range.” package-lock.json is the record of what actually got installed, so don’t delete it—put it in Git
Just being able to read this one file means you can figure out on your own how to run a project you spotted on GitHub.