You add an engineer to the team. Day one goes on laptop setup. Day two goes on finding out which of the three READMEs is current. By Thursday they have a running app, a Slack thread full of "oh, you also need toβ¦", and no commit.
None of that is the new person's fault. It's the repo's.
A survey of 411 developers at Microsoft (Rastogi et al., ESEM 2015) asked what slowed down a new hire's first contribution. 267 of them named missing project documentation. Not the codebase, not the tooling. The docs.
We add engineers to client teams for a living, so we see this from the joining side a lot. The test we use is simple: could a competent stranger make a meaningful change in their first week without interrupting anyone? Below is how to make the answer yes, and how to keep it yes, with things you can drop into a repo today.
1. One command from clone to running app
If setup is a page of steps, the steps are already wrong somewhere. Put them in code.
# Makefile
.PHONY: setup dev test seed
setup: ## First run after cloning
cp -n .env.example .env || true
docker compose up -d db redis
npm ci
npm run db:migrate
$(MAKE) seed
seed: ## Realistic fake data, never a production copy
npm run db:seed
dev:
npm run dev
test:
npm test
cp -n keeps someone's edited .env safe on a second run. And the seed script matters more than it looks. A new engineer staring at an empty dashboard can't tell a broken page from an empty one.
If you want to remove "works on my machine" entirely, add a dev container so the editor builds the environment for them:
// .devcontainer/devcontainer.json
{
"name": "app",
"dockerComposeFile": "../docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"postCreateCommand": "make setup",
"forwardPorts": [3000]
}
2. Test the setup in CI, or it will rot
Every team has a README that was true once. The fix is to run the onboarding path on a clean machine on a schedule, exactly as a new hire would.
# .github/workflows/onboarding.yml
name: onboarding-path
on:
schedule:
- cron: "0 6 * * 1" # every Monday
pull_request:
paths:
- "Makefile"
- "docker-compose.yml"
- ".env.example"
- "package*.json"
jobs:
fresh-clone:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
- run: make setup
- run: make test
- name: App boots and answers
run: |
npm run start &
npx wait-on http://localhost:3000/health --timeout 60000
When this goes red, the onboarding path broke for the next person, and you found out before they did.
3. Write down the five things nobody writes down
Code explains what. New people get stuck on why and where. A short ONBOARDING.md beats a long wiki that nobody owns:
# Onboarding
## Your first day
- `make setup`, then `make dev`. If either fails, that's a bug: open an issue.
- Log in as `admin@example.test` / password in `.env.example`.
## How work flows here
- Tickets: [board link]. Pick from the `good-first-change` label.
- Branches: `feat/<ticket-id>-short-name`. PRs need one review.
- Definition of done: tests pass, preview deploy checked, ticket updated.
## Where things live
- API routes: `src/api/`. Background jobs: `src/jobs/`.
- Feature flags: `src/flags.ts`. Never deploy dark code without one.
## Things that will surprise you
- Invoices use the customer's timezone, not UTC. See `docs/adr/007`.
- The `legacy_orders` table is still written by the old system. Read-only.
## Who decides what
- Product questions: @priya. Architecture: @sam. Deploys: anyone, after review.
That "Things that will surprise you" section is the most valuable part of the file. It's where the context that usually lives in one long-serving person's head gets written down.
4. Keep a queue of real first changes
"Read the code for a week" isn't onboarding. A labelled queue of small, real, low-risk changes is: a validation message, a missing test, a small UI fix. Each one should touch the full path, from branch to review to deploy, so the new engineer learns the pipeline on something that can't hurt.
# See what's ready for someone new
gh issue list --label good-first-change --state open
If that list is empty, your next new hire spends their first week waiting.
5. Record decisions where the code is
Short architecture decision records (ADRs) answer the question every new engineer eventually asks: "why on earth is it done like this?"
# ADR 007: Invoice dates use the customer's timezone
Status: accepted, 2025-11-03
Context: Customers in Australia saw invoices dated "yesterday".
Decision: Store UTC, render and group by the customer's timezone.
Consequences: Reports must pass the timezone explicitly. See `src/reports/tz.ts`.
Ten lines like that save a day of archaeology, and stop someone "fixing" the thing that was deliberate.
Why this matters beyond the first week
The same gaps cost you again later. A study of turnover at Chrome and a project at Avaya (Rigby et al., ICSE 2016) found that naming successors in advance cut the expected knowledge loss by up to fifteen percent. Written context is the cheapest way to have a successor ready.
It also decides whether adding people helps at all. If you're bringing in outside engineers to join your team, everything above is the prerequisite: they work in your process, and if the process only lives in people's heads, more engineers just means a longer queue at your tech lead. We wrote about that trade-off, and when a self-directing team is the better buy, in staff augmentation vs dedicated teams: the failure mode of each.
Your turn: what's the one thing a new engineer on your team always gets stuck on? We'd like to collect the strange ones.
From the team at Redlio Labs, where we join product teams and build software with them.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more