Skip to content

Commit 4419408

Browse files
committed
Publish production Node.js API starter
0 parents  commit 4419408

18 files changed

Lines changed: 3711 additions & 0 deletions

.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
NODE_ENV=development
2+
PORT=3000
3+
LOG_LEVEL=info
4+
TRUST_PROXY=false
5+
SHUTDOWN_TIMEOUT_MS=10000

.github/workflows/ci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: CI
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
permissions:
7+
contents: read
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
timeout-minutes: 10
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-node@v4
15+
with:
16+
node-version: 22
17+
cache: npm
18+
- run: npm ci
19+
- run: npm run lint
20+
- run: npm test

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
.env
3+
coverage/
4+
*.log
5+
.DS_Store

Dockerfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
FROM node:22-alpine AS dependencies
2+
WORKDIR /app
3+
COPY package*.json ./
4+
RUN npm ci --omit=dev
5+
6+
FROM node:22-alpine
7+
ENV NODE_ENV=production
8+
WORKDIR /app
9+
USER node
10+
COPY --chown=node:node --from=dependencies /app/node_modules ./node_modules
11+
COPY --chown=node:node package.json ./
12+
COPY --chown=node:node src ./src
13+
EXPOSE 3000
14+
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1:3000/health/live || exit 1
15+
CMD ["node", "src/server.js"]

LICENSE

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Manikandan Menon
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6+
7+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Production Node.js API Starter
2+
3+
[![CI](https://github.com/ManikandaMkM/node-production-api-starter/actions/workflows/ci.yml/badge.svg)](https://github.com/ManikandaMkM/node-production-api-starter/actions/workflows/ci.yml)
4+
[![Node.js](https://img.shields.io/badge/Node.js-22-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
5+
[![License](https://img.shields.io/badge/license-MIT-0B6E63)](LICENSE)
6+
7+
A deliberately small Express 5 starter demonstrating production concerns often missing from hello-world APIs: validated configuration, structured logging, request IDs, secure defaults, consistent errors, health probes, graceful shutdown, tests, CI, and a non-root container.
8+
9+
## Quick start
10+
11+
```bash
12+
cp .env.example .env
13+
npm install
14+
npm run dev
15+
```
16+
17+
```bash
18+
curl http://localhost:3000/health/ready
19+
curl -X POST http://localhost:3000/api/v1/echo \
20+
-H 'content-type: application/json' \
21+
-d '{"message":"hello"}'
22+
```
23+
24+
## Included patterns
25+
26+
- Express 5 with versioned routes
27+
- Zod environment and request validation
28+
- Helmet security headers and disabled framework fingerprinting
29+
- JSON logs with sensitive-header redaction
30+
- Request correlation through `x-request-id`
31+
- Stable error envelopes that avoid leaking internals
32+
- Separate liveness and readiness endpoints
33+
- Bounded JSON bodies and configurable proxy trust
34+
- Graceful `SIGTERM`/`SIGINT` shutdown
35+
- Vitest and Supertest coverage
36+
- Least-privilege container runtime
37+
- Dependency-cached GitHub Actions CI
38+
39+
## Response shape
40+
41+
```json
42+
{
43+
"error": {
44+
"code": "VALIDATION_ERROR",
45+
"message": "Request body is invalid",
46+
"requestId": "d36760ab-5a5d-45e3-aaf7-0c58ad6d020e"
47+
}
48+
}
49+
```
50+
51+
## Production checklist
52+
53+
This starter provides foundations, not a universal security claim. Before launch, add authentication and authorization for your domain, datastore readiness checks, rate limiting at the edge, CORS rules, secret management, observability export, backups, dependency scanning, and a deployment-specific rollback plan.
54+
55+
## Design principles
56+
57+
1. Fail fast when configuration is invalid.
58+
2. Make every request traceable without logging secrets.
59+
3. Keep operational probes independent from business routes.
60+
4. Return useful client errors and private server errors.
61+
5. Make shutdown behavior explicit and testable.
62+
63+
Built as a public engineering reference by [Manikandan Menon](https://github.com/ManikandaMkM).

SECURITY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Security policy
2+
3+
Please report vulnerabilities privately through GitHub's **Report a vulnerability** feature. Do not open a public issue containing exploit details, credentials, or personal data.
4+
5+
This is a generic reference implementation. Review its dependencies, rate limits, authentication, authorization, and data controls for your own threat model before production use.

eslint.config.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import globals from "globals";
2+
3+
export default [{
4+
files: ["**/*.js"],
5+
languageOptions: { ecmaVersion: "latest", sourceType: "module", globals: globals.node },
6+
rules: {
7+
"no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
8+
"no-console": "error",
9+
eqeqeq: ["error", "always"],
10+
},
11+
}];

0 commit comments

Comments
 (0)