Production-ready Node.js API build framework — opinionated, layered, and ready to ship.
A pnpm monorepo of composable packages that cover everything from structured logging and typed HTTP clients to JWT auth, Fastify plugins, and feature flags. Two example services demonstrate the full stack end-to-end.
| Tool | Minimum version | Install |
|---|---|---|
| Node.js | 22.0.0 | nodejs.org/en/download or via nvm / nvm-windows |
| pnpm | 9.0.0 | npm install -g pnpm |
Tip — Node version manager (recommended)
# macOS / Linux curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash nvm install 22 nvm use 22 # Windows (PowerShell — run as Administrator) winget install CoreyButler.NVMforWindows nvm install 22 nvm use 22
# Via npm (works on all platforms)
npm install -g pnpm
# Via Corepack (bundled with Node ≥ 16.9)
corepack enable
corepack prepare pnpm@latest --activateVerify everything is ready:
node --version # v22.x.x or higher
pnpm --version # 9.x.x or higher# 1. Clone
git clone https://github.com/your-org/cc-api-framework.git
cd cc-api-framework
# 2. Install all dependencies (hoisted, deduped by pnpm)
pnpm install
# 3. Build every package in dependency order
pnpm build
# 4. Copy env files and fill in values
cp examples/core-services/order-service/.env.example examples/core-services/order-service/.env
cp examples/front-end-services/user-api/.env.example examples/front-end-services/user-api/.env
# 5. Start both example services with file-watch reload
pnpm devBoth services will be live:
| Service | URL | Description |
|---|---|---|
| user-api (front-end) | http://localhost:3000 | Public-facing API — JWT, CORS, rate limiting, OpenAPI |
| order-service (core) | http://localhost:3001 | Internal API — service-to-service auth only |
cc-api-framework/
├── packages/ # Publishable framework packages
│ ├── errors/ # Typed HTTP error hierarchy
│ ├── logger/ # Structured JSON logger (Pino)
│ ├── networking/ # HTTP client with circuit breaker + retry
│ ├── config/ # Fail-fast env config (Zod)
│ ├── auth/ # JWT, API key, OAuth 2.0
│ ├── fastify-plugins/ # Production Fastify plugin suite
│ ├── feature-config/ # Remote feature flags
│ └── testing/ # Test helpers (not published)
│
├── examples/
│ ├── front-end-services/
│ │ └── user-api/ # Full-stack service template
│ └── core-services/
│ └── order-service/ # Internal service template
│
├── package.json # Root scripts (turbo run …)
├── pnpm-workspace.yaml # Workspace package globs
├── turbo.json # Turbo task pipeline
└── tsconfig.base.json # Shared TS strict compiler options
| Package | Description |
|---|---|
@cc-api-framework/errors |
Typed error class hierarchy (NotFoundError, UnauthorizedError, ValidationError, …) that map cleanly to HTTP status codes |
@cc-api-framework/logger |
Structured JSON logging via Pino with AsyncLocalStorage-backed correlation ID propagation across async call chains |
@cc-api-framework/networking |
HTTP client built on undici — full-jitter retry, circuit breaker, OAuth bearer token injection, typed ApiResponse discriminated union |
@cc-api-framework/config |
Zod-validated defineConfig() — validates process.env at startup and throws a human-readable error rather than failing silently at request time |
@cc-api-framework/auth |
JWT verification (HS256, RS256, JWKS auto-fetch + cache), API key plugin, OAuth 2.0 client_credentials / refresh_token token store |
@cc-api-framework/fastify-plugins |
Correlation ID, structured request logger, error handler, CORS, rate limiter, graceful shutdown, OpenAPI 3.1 + Swagger UI, internal service auth, named external API clients |
@cc-api-framework/feature-config |
Remote feature flag configuration loaded from a JSON endpoint with a local fallback |
@cc-api-framework/testing |
MockNetworkingClient, withCorrelationContext(), buildTestApp() — shared test helpers (private, not published) |
Customer-facing API template. Demonstrates:
jwtPlugin— verifies Bearer tokens (HS256 in dev; swap forrs256-jwksin production)corsPlugin— per-origin allow-list fromALLOWED_ORIGINSrateLimitPlugin— IP-based sliding windowopenapiPlugin— auto-generated OpenAPI 3.1 spec at/openapi.json+ Swagger UI at/docsexternalApiPlugin— named HTTP client fororder-servicewith auto-forwarded correlation IDerrorHandlerPlugin— maps typed errors to JSON HTTP responsescorrelationIdPlugin— stamps every request withx-correlation-idregisterGracefulShutdown— drains in-flight requests onSIGTERM
Internal (mesh-only) service template. Demonstrates:
internalAuthPlugin— rejects requests missing a validx-service-authtokenfeatureConfigPlugin— polls a remote JSON endpoint for feature flags with a local default fallback- No CORS, no rate limiting, no public JWT — security is handled at the front-end-services tier
Each service reads its config at startup via @cc-api-framework/config. Copy the example file and edit:
# order-service
cp examples/core-services/order-service/.env.example \
examples/core-services/order-service/.env
# user-api
cp examples/front-end-services/user-api/.env.example \
examples/front-end-services/user-api/.envorder-service (port 3001)
| Variable | Required | Description |
|---|---|---|
PORT |
no (3001) | HTTP listen port |
NODE_ENV |
no (development) | development / production / test |
LOG_LEVEL |
no (info) | fatal error warn info debug trace |
SERVICE_VERSION |
no (0.0.0) | Emitted in logs |
SERVICE_AUTH_TOKEN |
yes | Shared secret callers must send on x-service-auth (min 16 chars) |
FEATURE_CONFIG_URL |
no | URL of remote feature-flag JSON |
user-api (port 3000)
| Variable | Required | Description |
|---|---|---|
PORT |
no (3000) | HTTP listen port |
NODE_ENV |
no (development) | |
LOG_LEVEL |
no (info) | |
SERVICE_VERSION |
no (0.0.0) | |
JWT_SECRET |
yes | HS256 signing secret (min 32 chars) |
ALLOWED_ORIGINS |
no | Comma-separated CORS origins |
SERVICE_AUTH_TOKEN |
yes | Token this service sends to order-service (min 16 chars) |
ORDER_SERVICE_URL |
no (http://localhost:3001) | Base URL for order-service |
FEATURE_CONFIG_URL |
no | URL of remote feature-flag JSON |
The
.envfiles are gitignored (*.envin.gitignore). Never commit secrets.
Run from the repo root. Turbo executes tasks in dependency order and caches outputs.
pnpm install # Install all workspace dependencies
pnpm build # Compile every package (TypeScript → dist/)
pnpm dev # Start example services with --watch reload
pnpm test # Run all test suites (vitest)
pnpm typecheck # Type-check without emitting (fast CI check)
pnpm clean # Delete all dist/ and .turbo/ cachesRun a single package:
pnpm --filter @cc-api-framework/auth test
pnpm --filter @acme/user-api dev
pnpm --filter @acme/order-service buildAll packages extend tsconfig.base.json which enables a strict set of compiler options:
| Option | Effect |
|---|---|
strict: true |
Enables strictNullChecks, noImplicitAny, etc. |
exactOptionalPropertyTypes |
{ x?: string } disallows explicitly passing undefined |
noUncheckedIndexedAccess |
Array/object index access returns T | undefined |
noPropertyAccessFromIndexSignature |
Indexed properties must use bracket notation |
noImplicitOverride |
Class method overrides must use override keyword |
Target: ES2022, module system: NodeNext (native ESM).
See PUBLISHING.md for instructions on publishing packages to npm and setting up a private registry.