Every JavaScript or TypeScript project has a package.json at its root. It is the file your package manager reads to know what to install, which scripts to run, and how your project is versioned.
Generate a package.json
The fastest way to get started:
Or with pnpm:
The -y flag answers "yes" to all questions. You get a minimal file you can edit by hand.
Fully annotated example
{
"name": "my-project",
"version": "1.0.0",
"description": "Short description of the project",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"test": "vitest"
},
"dependencies": {
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
"devDependencies": {
"vite": "^5.2.0",
"vitest": "^1.6.0",
"@types/react": "^18.3.0"
},
"engines": {
"node": ">=20.0.0"
}
}The essential fields
name: unique project identifier (lowercase, no spaces). Required if you publish to npm.
version: semver version number (MAJOR.MINOR.PATCH). Start at 1.0.0 for a published project, 0.1.0 for one in progress.
type: "module" to use import/export (ESM), omit or "commonjs" for require(). The value "module" is the standard in 2026.
scripts: commands you run with pnpm run <name>. Common names: dev, build, test, start, lint.
dependencies: packages needed in production (runtime).
devDependencies: packages used only during development (compilers, linters, tests). They are not included in the final build.
engines: minimum Node version required. Useful to avoid surprises on machines with an old version.
peerDependencies
A fourth dependency type exists: peerDependencies. Use it when developing a library that assumes the host application has already installed a package (e.g., a React plugin that requires React 18). Users of your library must install these peers themselves.
Editing package.json by hand
Contrary to what you might think, editing package.json by hand is completely normal. Add a "lint": "eslint ." script, change the type, adjust a version. After each change, run pnpm install to resync the lockfile.