Project Setup Best Practices
Standards for Node service repositories that onboard fast, build in CI, and deploy predictably.
How to Use This List
- Apply when creating repos from templates or generators.
- Review during architecture reviews before adding a second deployable.
- Enforce layout and scripts via template CI, not informal conventions.
A - Repository Layout
- Use
src/for runtime code and a dedicated test location. Picktest/or colocated*.test.ts, not both. - One primary deployable per app folder in monorepos.
apps/billing-apimaps to one container image. - Keep configuration at the repo root or app root consistently.
tsconfig, ESLint, and Dockerfile discoverability matters. - Commit
.env.example, never secrets. Document every required variable with safe defaults. - Include
health(and optionallyready) routes from day one. Load balancers and orchestrators need them.
B - TypeScript & Scripts
- Split
tsconfig.jsonandtsconfig.build.json. Typecheck tests; emit onlysrc/todist/. - Use
NodeNextmodule resolution on Node 24. Matches ESMimportbehavior in production. - Export
createApp()(or equivalent) from servers. Enables HTTP integration tests without binding ports. - Scripts:
dev,build,start,test,typecheck. Same commands locally and in CI. - Run production
startagainst compiled JS. Nottsxin containers.
C - Docker & Runtime
- Pin Node patch in Dockerfile (
node:24.18.0-alpine). Align withenginesinpackage.json. - Multi-stage builds: deps, build, runtime. Production image excludes TypeScript and devDependencies.
- Copy lockfile before source for layer cache.
npm cilayer rebuilds only when deps change. - Set
NODE_ENV=productionin runtime stage. Frameworks and log verbosity depend on it. - Document exposed port and health path in README. Matches K8s probes and compose files.
D - Monorepo & Scaffolding
- Shared code in
packages/, deployables inapps/. Apps never import sibling apps directly. - Maintain an internal template repo with CI. New services inherit current Express/Fastify/Nest pins.
- Use Turborepo or Nx when 3+ packages need orchestration. Plain npm scripts stop scaling.
- Path-filter CI deploys per service. Unrelated API changes must not redeploy billing.
- Version internal contracts package with breaking-change discipline. Zod schema changes affect multiple apps.
E - Documentation & Governance
- README quick start:
npm ci, env copy,npm run dev. Three steps to running server. - Record framework choice in ADR for new services. Express vs Fastify vs Nest is not arbitrary per repo.
- Add sample test in scaffold. CI never ships with empty
npm testpassing trivially. -
.gitignorecoversnode_modules,dist,.env, coverage. Prevent accidental commits. - Rename and scrub template placeholders before first deploy. Default service names propagate to metrics and logs.
FAQs
Should tests live in test/ or src/?
Either works. test/ simplifies dist/ output; colocated tests improve locality. Pick one per org.
When do we adopt a monorepo?
When two deployables share evolving contracts and you want atomic PRs. Not for a single API with copy-paste helpers.
Is a Dockerfile required for every service?
Yes for containerized deploys. Serverless uses packaging config instead but same build/typecheck scripts apply.
What belongs in a template repo?
Layout, scripts, ESLint, sample test, Docker, CI workflow, .env.example, and README - proven green on every tag.
How do we handle multiple Node versions during migration?
Widen engines temporarily, pin CI matrix, migrate app-by-app, then tighten engine-strict.
Should we commit dist/?
No for container builds that compile in CI/Docker. Yes only for atypical git-deploy flows (avoid if possible).
How flat should src/ be?
Group by domain (routes/, services/) not by layer only. Depth grows with feature count, not upfront.
Do workers share the same layout?
Yes: src/worker.ts, same scripts, separate Dockerfile or process command. Reuse packages/ for job payloads.
How do preview environments fit?
Each PR deploys one app from apps/* with path filters; document naming in platform runbooks.
What is the minimum CI check on scaffold?
npm ci, npm run typecheck, npm test, npm run build, Docker build (if used).
Related
- Project Setup Basics - layout examples
- Scaffolding APIs - templates and CLIs
- Multi-Service Monorepo - app vs package rules
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.