TK
All writing
Engineering

package.json scripts you should be using

Your package.json scripts are an underused automation surface. Pre/post hooks, running scripts in series and parallel, passing args, and the conventions that make a repo easy for anyone to run.

Tanveer Khan7 min read

The scripts block in package.json is the front door to your project — it's how anyone (including future you) knows how to build, test and run it. Most repos barely use it. A little structure here saves everyone time.

The conventional names

Stick to the names people expect so a newcomer can guess them: dev, build, start, test, lint, format. Predictability is the whole point.

package.json
json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint .",
    "format": "prettier --write .",
    "test": "vitest",
    "typecheck": "tsc --noEmit"
  }
}

pre and post hooks run automatically

npm runs a script named pre<x> before <x> and post<x> after it, automatically. 'prebuild' runs before 'build' with no wiring.

package.json
json
{
  "scripts": {
    "prebuild": "npm run typecheck && npm run lint",
    "build": "next build"
  }
}

Series vs parallel

package.json
json
{
  "scripts": {
    "check": "npm run lint && npm run typecheck",
    "ci": "npm run check && npm run test"
  }
}

&& runs in series and stops on the first failure (what you usually want for CI gates). For running things truly in parallel — a dev server plus a watcher — reach for a tiny tool like npm-run-all (run-p) or concurrently rather than backgrounding with &.

Passing arguments

terminal
bash
# pass flags through with --
npm run test -- --watch
npm run lint -- --fix

Use the conventional names, lean on pre/post hooks for gates, chain with && for CI, and document anything unusual. A good scripts block means 'clone, npm install, npm run dev' just works — the kindest thing you can do for anyone who opens your repo.