Tags: web-dev concept

Local Development Setup

Date: 2026-08-17


Getting a working environment on a new machine. The cost is paid by every new joiner, every machine change and every return to a dormant project — and it’s almost never measured, which is why it silently becomes a day.


Local development setup is everything needed between cloning a repository and having a running application you can change.

The measurement nobody takes

clone → running application

GOOD          under 10 minutes,
              two commands

TYPICAL       half a day, several
              people asked

BAD           "ask Dave, he set it up"

Time this on the next new joiner. It’s the only way the cost becomes visible, and it’s a number that only ever goes up unless someone owns it.

The target

git clone …
cd project
make setup      # or npm run setup
npm run dev

Two commands. Everything else — dependency install, service startup, database creation, migration, seeding, environment file — happens inside them.

{
  "scripts": {
    "setup": "npm ci && docker compose up -d && npm run db:migrate && npm run db:seed && cp -n .env.example .env.local",
    "dev": "docker compose up -d && vite"
  }
}

What has to be handled

RUNTIME VERSION      .nvmrc, .tool-versions
                     → and a check that
                       fails loudly on
                       mismatch

DEPENDENCIES         npm ci from the
                     lockfile — Lockfiles

SERVICES             docker compose
                     database, Redis,
                     search — Containers

DATABASE             created, migrated,
                     SEEDED
                     — Test Data

ENVIRONMENT          .env.example copied,
                     with working defaults
                     — Environment Configuration

CREDENTIALS          which are needed, and
                     how to get them

See: Lockfiles · Containers · Test Data · Environment Configuration

Seeding is the step most often missing. An empty database means the application technically runs and nothing is usable — a new developer’s first hour goes on creating a product by hand.

A good seed script includes the edge cases: an order with 50 items, a customer with none, an out-of-stock product, a very long product name. It’s development data and test data at once.

Fail loudly on the wrong versions

{
  "engines": { "node": ">=24 <25" },
  "packageManager": "pnpm@9.0.0"
}

A mismatched Node version produces bizarre errors that take an hour to trace back to the cause. A check that says “you’re on Node 18, this needs 20” saves that hour every time.

Documentation that stays true

README
├─ what this is                 2 lines
├─ prerequisites                versions
├─ setup                        the commands
├─ running                      the commands
├─ common problems              3–5 entries
└─ where to get credentials

Documentation drifts; scripts don’t. Anything that can be a script should be — the README should say npm run setup, not list twelve steps that were accurate last year.

The strongest test of a setup guide is a new person following it without asking anything, and updating it as they go. That’s the only reliable way it stays correct.

Where it degrades

  • Undocumented manual steps. “You also need to create the bucket”
  • Credentials with no route. A new joiner blocked on someone being online
  • Platform assumptions. Instructions that work on macOS and not on Windows or Linux
  • Version drift. A dependency bumping its Node requirement without the docs changing
  • Nobody re-runs it. The setup path rots because everyone already has a working machine

Have CI run the setup path periodically, or on a schedule, from a clean state. It’s the only way the rot is detected before it costs somebody a day.

Devcontainers

The stronger option where the stack is genuinely complex:

// .devcontainer/devcontainer.json
{
  "image": "mcr.microsoft.com/devcontainers/javascript-node:24",
  "forwardPorts": [3000, 5432],
  "postCreateCommand": "npm ci && npm run db:seed"
}

Everything defined in the repository; the editor builds it. Genuinely good for onboarding and for a heterogeneous team.

The cost is the file-watching performance penalty on macOS and Windows, which is paid on every save — so it’s a better fit for backend work than for front-end development with hot reload — Containers.