| name | npm-patterns |
| description | Package management discipline for any JavaScript/TypeScript project: dependency declaration, semver, scripts conventions, lockfile hygiene, package-manager detection (npm/yarn/pnpm). Stack-agnostic — referenced by every JS/TS framework plugin in the marketplace.
Use this skill to:
- Add a dependency correctly (right field, right semver range).
- Pick the project's package manager from lockfile.
- Define `scripts` entries that match conventions.
- Avoid lockfile mistakes (manual edits, wrong commits).
Do NOT use this skill for:
- Code-level conventions (see the active framework plugin's conventions skill).
- Framework-specific package patterns (NestJS modules, Angular schematics, Expo SDK choice etc.).
|
npm / yarn / pnpm Patterns (stack-agnostic)
This skill consolidates package management idioms applicable to any JS/TS project — backend, frontend, mobile, library. Apply when modifying package.json, adding dependencies, or defining scripts.
Detect the package manager
Look at the lockfile in the project root:
| Lockfile present | Use |
|---|
package-lock.json | npm |
yarn.lock | yarn |
pnpm-lock.yaml | pnpm |
bun.lockb / bun.lock | bun (rare; mostly drop-in for npm) |
| (none) | npm — but flag in DECISIONS that no lockfile is committed |
Also check package.json "packageManager" field (e.g. "packageManager": "pnpm@8.6.0") — when present, it overrides lockfile inference.
Map common commands:
| Action | npm | yarn | pnpm |
|---|
| Install all | npm install | yarn install | pnpm install |
| Add runtime dep | npm install pkg | yarn add pkg | pnpm add pkg |
| Add dev dep | npm install -D pkg | yarn add -D pkg | pnpm add -D pkg |
| Run script | npm run x | yarn x | pnpm x |
| Update lockfile | npm install | yarn install | pnpm install |
Always run the install command after editing package.json — never edit the lockfile by hand.
Dependency fields
| Field | Use for |
|---|
dependencies | Runtime — what the production app needs to run (express, react, pinia, axios). |
devDependencies | Dev tooling — bundlers, test runners, linters, type definitions, dev servers. |
peerDependencies | Library authors only — declares what host app must provide (e.g., react for a React component library). |
optionalDependencies | Rare — install failure should not break install (native binaries with fallbacks). |
bundledDependencies | Rare — packaged inside npm pack tarball. |
Rule of thumb: if the code is bundled into the production output for runtime use, it's a dependency. If it only runs during npm test / npm run build / lint, it's a devDependency.
Frontend nuance: bundlers (Vite/Webpack/esbuild) often tree-shake unused exports — but the package still belongs in dependencies if any production-rendered code imports it.
Semver discipline
| Range | Meaning | When to use |
|---|
^1.2.3 | >=1.2.3 <2.0.0 (no breaking changes) | Default — most deps |
~1.2.3 | >=1.2.3 <1.3.0 (only patch) | Conservative — production-critical |
1.2.3 | Exact | When you've debugged a specific version (rare) |
>=1.2.3 | Any version >=1.2.3 | Almost never — too loose |
* or latest | Anything | NEVER. Reproducible builds matter. |
git+https://... | Git ref | Only as last resort; pin to commit SHA. |
Default: ^x.y.z. Lockfile pins exact versions for reproducibility — that's what makes ^ safe.
scripts conventions
Common script names (be consistent — these are de-facto standard):
| Script | Purpose |
|---|
start | Production entry: node dist/index.js (Node) or static server (frontend) |
dev | Dev entry: nodemon / tsx watch / vite / next dev / ng serve |
build | Compile/bundle: tsc, vite build, next build, ng build, esbuild, webpack |
test | Test runner: jest, vitest, mocha, ng test |
test:watch | Watch-mode tests |
test:coverage | Coverage report |
test:e2e | E2E tests (Playwright/Cypress/Detox) |
lint | eslint . |
lint:fix | eslint . --fix |
format | prettier --write . |
format:check | prettier --check . |
typecheck | tsc --noEmit (or vue-tsc --noEmit for Vue) |
clean | Remove dist/, coverage/, .next/, out/ |
prepare | Auto-runs after install (husky setup, etc.) |
Don't invent new names without a reason. CI configs and other tools assume these.
Lockfile policy
- Always commit the lockfile to git.
- Never edit by hand. Always regenerate via the package manager.
- Match the package manager: don't commit
yarn.lock and package-lock.json simultaneously.
- Resolve conflicts by accepting one side, then running
<pm> install to regenerate.
- For library packages published to npm, lockfile is committed but not published (it's in
.npmignore by default).
engines field
Pin Node version when it matters (e.g., uses node:test requires ≥18, or your bundler requires ≥20):
{
"engines": {
"node": ">=18.0.0"
}
}
Add engines.npm only if you need a specific npm major version.
package.json type field
"type": "module" — files default to ESM. Use import/export. CJS files must use .cjs extension.
- Absent or
"type": "commonjs" — files default to CJS. Use require/module.exports. ESM files must use .mjs extension.
Don't change this unless the BA spec explicitly asks; switching modes mid-project is invasive (especially for backend Node projects).
Frontend bundler-driven projects (Vite/Webpack/Next/Angular CLI) typically use "type": "module" regardless — bundler handles output.
Workspaces (monorepos)
For monorepos:
{
"name": "my-monorepo",
"private": true,
"workspaces": ["apps/*", "packages/*"]
}
- pnpm: uses
pnpm-workspace.yaml instead.
- yarn: same
workspaces field; berry vs classic differ in detail.
- Monorepo runners (Nx, Turborepo, Lerna): override default install/build/test orchestration. Match what's installed.
Per-app package.json files declare app-specific deps; root-only deps go in root.
Dependency hygiene
- Run
npm audit (or equivalent) when adding deps; fix Critical/High before committing.
- Avoid
--force resolution unless you know what you're overriding and document it.
- Don't add deps for trivial utilities you can write in 5 lines (e.g., is-odd, padleft) — supply chain risk.
- Watch for typo-squatting:
lodash vs lodahs, chalk vs chal-k.
- For frontend: bundle size matters — measure before adding heavy deps (use
bundlephobia.com as a quick gauge).
Anti-patterns
- ❌
npm install --force without justification.
- ❌ Editing
package-lock.json / yarn.lock / pnpm-lock.yaml by hand.
- ❌ Using
* or latest as a version range.
- ❌ Adding the same package to both
dependencies and devDependencies.
- ❌ Committing
node_modules/.
- ❌ Mixing package managers (lockfile from one, install via another).
- ❌ Adding
engines.node without testing on the lower bound.
- ❌ For frontend: putting build-time tools in
dependencies (bloats npm ci for production-only installs).