Most repos get their README, CI and Dockerfile "later," and later turns into never. Here's a short checklist I run through when I start a new Node project. Each step takes a minute or two.

1. Pin your Node version and lock your dependencies

echo "20" > .nvmrc npm init -y npm install # creates package-lock.json, commit it 

Add an engines field so mismatches show up early:

"engines": { "node": ">=20" } 

2. A .gitignore you won't have to fix later

node_modules/ dist/ .env .env.* !.env.example coverage/ 

Commit a .env.example with placeholder keys so new contributors know which variables to set.

3. A README skeleton

A README only needs to answer a few questions. Start with headings and fill them in as you go:

# project-name One sentence: what this does and who it's for. ## Quick start npm ci cp .env.example .env npm run dev ## Scripts | Command | What it does | |-----------------|---------------------| | `npm test` | Run tests | | `npm run build` | Build to `./dist` | ## Configuration List each env var and its default. ## Contributing See CONTRIBUTING.md. ## License MIT 

The "Quick start" section matters most. If someone can't run your project from those three lines, fix the project or fix the lines.

4. CI on every push and PR

Save this as .github/workflows/ci.yml:

name: CI on: [push, pull_request] permissions: contents: read concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version-file: .nvmrc cache: npm - run: npm ci - run: npm run lint --if-present - run: npm test --if-present - run: npm run build --if-present 

A few details: --if-present keeps CI green before you've written a lint or test script. concurrency cancels the old run when you push again. contents: read limits the token to what CI needs.

5. A multi-stage Dockerfile

Build in one stage, ship only what runs:

FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build && npm prune --omit=dev FROM node:20-alpine WORKDIR /app COPY --from=build /app/node_modules ./node_modules COPY --from=build /app/dist ./dist USER node EXPOSE 3000 CMD ["node", "dist/server.js"] 

And a .dockerignore, so you don't copy node_modules or secrets into the build context:

node_modules .git .env* dist 

Running as the non-root node user is a one-line change that's easy to forget.

6. The small repo files

  • .github/dependabot.yml for weekly dependency PRs:
version: 2 updates: - package-ecosystem: npm directory: / schedule: { interval: weekly } 
  • .github/pull_request_template.md with a short "What / Why / How to test" list.
  • CONTRIBUTING.md and SECURITY.md, even if each is only a few lines. GitHub links them automatically.

The checklist

  • [ ] .nvmrc, engines, committed lockfile
  • [ ] .gitignore + .env.example
  • [ ] README with a working Quick start
  • [ ] CI workflow on push and PR
  • [ ] Multi-stage Dockerfile + .dockerignore
  • [ ] Dependabot, PR template, CONTRIBUTING, SECURITY

If you'd rather not write all of this by hand, I made the ShipKit GitHub Actions Starter Pack. It has 15 workflows (Node, Python and Go CI, Docker to GHCR, semver releases, deploys to Pages, Vercel and Fly, CodeQL and more) plus a repo template set: README, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, a PR template, issue templates, dependabot.yml and labeler.yml: https://8686702537545.gumroad.com/l/clhec?ref=devto-third

Last day: both packs are $9 each with code SHIPKIT9 until tonight, Thursday, Oct 15 at 11:59 PM CT. After that they're $15.

For the Docker side, the Docker & Dev Container Starter Pack ($15, or $9 with SHIPKIT9 today) has Dockerfiles for Node, Python, Go and static sites, three Compose stacks with healthchecks, and dev container configs: https://8686702537545.gumroad.com/l/bafiks?ref=devto-third

Want both? The ShipKit Complete bundle has both packs for $16 (SHIPKIT9 doesn't apply): https://8686702537545.gumroad.com/l/whlyio?ref=devto-third

If your app uses Postgres, Redis, MySQL or MongoDB with Docker Compose, there's also a free generator that writes the healthcheck and depends_on: condition: service_healthy block for you: https://8686702537545.gumroad.com/l/cumhuh?ref=devto-third (free, enter $0; it asks for an email). The snippets are starting points, so check them against your own setup.

Disclosure: I make ShipKit, which sells this pack.