Scaffolding APIs
Scaffolding creates a consistent starting point so every new service has the same layout, scripts, and quality gates.
Recipe
Quick-reference recipe card - copy-paste ready.
mkdir orders-api && cd orders-api
npm init -y
npm install express@5
npm install -D typescript@5.6 tsx @types/node @types/express eslint
npx --yes @nestjs/cli new orders-api --package-manager npm --strictWhen to reach for this:
- Bootstrapping a greenfield HTTP service.
- Standardizing org-wide folder layout and CI hooks.
- Avoiding copy-paste from an old repo with stale dependencies.
Working Example
# 1. Org template (preferred for teams)
git clone git@github.com:acme/node-api-template.git billing-api
cd billing-api
rm -rf .git && git init
npm ci
# 2. Or minimal manual scaffold
npm init -y
npm pkg set type=module
npm pkg set scripts.dev="tsx watch src/server.ts"
npm pkg set scripts.build="tsc -p tsconfig.build.json"
npm pkg set scripts.start="node dist/server.js"
npm pkg set scripts.test="node --import tsx --test"
npm install express@5
npm install -D typescript@5.6 tsx @types/node @types/express
npx tsc --init --module NodeNext --moduleResolution NodeNext --strict
mkdir -p src test// src/server.ts
import express from "express";
export function createApp() {
const app = express();
app.use(express.json());
app.get("/health", (_req, res) => res.json({ ok: true }));
return app;
}
if (import.meta.url === `file://${process.argv[1]}`) {
createApp().listen(3000);
}What this demonstrates:
- Template repos encode org decisions (ESLint, Docker, CI) once.
npm pkg setscripts without hand-editing JSON.createApp()export enables Supertest integration tests from day one.
Deep Dive
How It Works
npm initcreatespackage.json; frameworks add routing, DI, and conventions.- NestJS CLI generates modules, controllers, and
nest-cli.jsonbuild graph. - Fastify CLI and Express have lighter scaffolds - you bring more structure yourself.
- Template repos should run
npm ci && npm testin CI to prove they work.
Framework CLIs
| CLI | Command | Best for |
|---|---|---|
| NestJS 11 | npx @nestjs/cli new | Opinionated modules, DI, enterprise APIs |
| Fastify 5 | manual + @fastify/type-provider-typebox | Performance-first HTTP |
| Express 5 | manual / org template | Minimal middleware stacks |
TypeScript Notes
npm install -D typescript@5.6 tsx
# tsconfig: "module": "NodeNext", "strict": true- Scaffold with the same
modulesettings you use in production builds. - Add
test/and a sample test in the template so CI is never empty.
Gotchas
- Stale template dependencies - New services inherit old Express 4 pins. Fix: Renovate on the template repo; version template releases.
- CLI defaults wrong package manager - Nest prompts for yarn unless you pass
--package-manager npm. Fix: script the flags in docs. - Missing
createAppexport - Hard to integration-test servers that only calllisten()at import. Fix: export factory; start server inif (main)guard. - Copying .env from old projects - Secrets leak into git history. Fix: only
.env.examplein templates. - Over-generated Nest structure - Default CLI creates more folders than a small API needs. Fix: prune modules or use a slim internal template.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Internal npm create @acme/api | Standardized org generator | Solo experiments |
Turborepo create-turbo | Monorepo from day one | Single microservice |
Defer framework, raw node:http | Learning or ultra-minimal probe | Production CRUD APIs |
FAQs
Should we use npm init or a framework CLI?
Framework CLIs for NestJS; org templates for Express/Fastify where you want custom layout. npm init alone is never enough for production APIs.
How do we maintain a template repo?
Treat it as a product: CI, dependency bumps, changelog, tagged releases. New services pin a template version or branch.
What files must every template include?
package.json scripts, tsconfig, .gitignore, .env.example, Dockerfile, sample test, ESLint config, and README quick start.
Can we scaffold into a monorepo apps/ folder?
Yes. Run generator inside apps/billing-api and wire root workspaces after. Update root turbo.json pipeline.
Express 5 or Fastify 5 default?
Follow org ADR. Fastify for throughput-sensitive APIs; Express for largest middleware ecosystem and team familiarity.
How do we test a template?
CI job: clone fresh, npm ci, npm test, npm run build, Docker build. Fail template release if any step fails.
Should templates include Prisma/TypeORM?
Only if standardized org-wide. Otherwise add data layer in a second PR to keep templates framework-agnostic longer.
What about git hooks in scaffolds?
Include Husky + lint-staged optional profile. Document skip for contributors who rely on CI-only gates.
How do we rename after nest new?
Update package.json name, K8s manifests, and Docker image tags. Nest project name propagates to several files.
Is npx @nestjs/cli safe in CI?
Pin CLI version in devDependencies or use npx @nestjs/cli@11.x for reproducible generation docs.
Related
- Project Setup Basics - standard folder layout
- Turborepo for Node - monorepo scaffold next step
- Nx for Node Backends - generator-based setup
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.