StackForge, the API scaffold generator with Node.js + Express, including:
- register
- login
- check logged-in session
- refresh token rotation
- logout
- Node.js (ESM)
- Express 5
- JWT (access token)
- Refresh token in
httpOnlycookie - Password hashing with bcrypt
- Validation with Zod
- Local persistence with lowdb (JSON file)
- Repository layer ready to evolve to relational or non-relational databases
- Install dependencies:
pnpm install- Create
.envfrom the example:
node -e "require('node:fs').copyFileSync('.env.example', '.env')"- Start development:
pnpm devOr run in normal mode:
pnpm startCreate a new auth API project in the default workspace folder:
pnpm dev:new-project -- your-api-nameThe project is created at developers/projects/your-api-name.
Profiles:
lite(default): smaller template with faster startupfull: includes tests, docs, and CI
Examples:
pnpm dev:new-project -- your-api-name --full
pnpm dev:new-project -- your-api-name --lang=typescript
pnpm dev:new-project -- your-api-name --ts
pnpm dev:new-project -- your-api-name --full --lang=typescript
pnpm dev:new-project -- your-api-name --db=mysql
pnpm dev:new-project -- your-api-name --db=sqlite
pnpm dev:new-project -- your-api-name --db=sqlserver
pnpm dev:new-project -- your-api-name --db=json
pnpm dev:new-project -- your-api-name --architecture=mvc
pnpm dev:new-project -- your-api-name --architecture=clean
pnpm dev:new-project -- your-api-name --api=graphql
pnpm dev:new-project -- your-api-name --api=hybrid
pnpm dev:new-project -- your-api-name --pm=npm
pnpm dev:new-project -- your-api-name --pm=yarn
pnpm dev:new-project -- your-api-name --pm=bun
pnpm dev:new-project -- your-api-name --features=both
pnpm dev:new-project -- your-api-name --features=none
pnpm dev:new-project -- --interactiveWhen using --lang=typescript, the generated project uses .ts files for core application code and keeps the scaffold lean by omitting the scripts folder.
Generation guarantees:
--lang=javascript: generates runtime files in JavaScript (index.js,src/**/*.js) with Vitest config in.mjsand no TypeScript project artifacts.--lang=typescript: generates runtime files in TypeScript (index.ts,src/**/*.ts) with imports aligned to TS and runtime start compatible with Docker (pnpm start).- Docker startup stays language-agnostic through
pnpm start, preventing hardcodedindex.jsdrift.
Database options:
--db=json: local JSON database (no Prisma dependencies in generated project)--db=postgresql|mysql|sqlite|sqlserver: relational mode with Prisma configured for selected provider
Architecture options:
--architecture=layered: layered modules/repositories flow (default)--architecture=mvc: generatesconfig,controllers,db,middlewares,models,routes,utils, andviewsundersrc/and adds the MVC architecture guide--architecture=clean: adds clean architecture folders and guide
API style options:
--api=rest: REST endpoints only (default)--api=graphql: GraphQL endpoint scaffold (/graphql)--api=hybrid: REST + GraphQL together
Package manager options:
--pm=pnpm: keep pnpm commands and lockfile (default)--pm=npm: rewrite generated commands/scripts for npm usage--pm=yarn: rewrite generated commands/scripts for yarn usage--pm=bun: rewrite generated commands/scripts for bun usage
Runtime smoke note:
yarnsmoke runs throughcorepackwhen available.bunsmoke requires bun runtime support in the environment and is skipped when unavailable.
Feature set options:
--features=auth: authentication scaffold only (default)--features=email: email configuration scaffold only--features=both: authentication + email configuration--features=none: only health/docs baseline (without auth routes)
Scaffold maintenance route:
DELETE /api/scaffold/projects/downloads: removes generated download artifacts from the server
Modern auth baseline in generated projects:
- short-lived access token + rotating refresh token flow
- refresh token in secure
httpOnlycookie - CSRF protection for cookie-based session flows
- login throttling/rate-limit middleware
- structured logging and request context for observability
Integration-ready architecture for future evolution:
- layered modules (
controllers,services,repositories) - Prisma + schema management prepared for relational providers
- OpenAPI documentation scaffold and integration test entry points
- environment-driven configuration for cloud and container workflows
Quick team guide:
developers/README.md
- Contribution guide:
CONTRIBUTING.md - Security policy:
SECURITY.md - Code of conduct:
CODE_OF_CONDUCT.md - PR template:
.github/pull_request_template.md - Issue templates:
.github/ISSUE_TEMPLATE/
Local quality commands:
pnpm lint
pnpm format:check
pnpm typecheck
pnpm test
pnpm auditCI pipeline:
- file:
.github/workflows/ci.yml - triggers:
push(main/master) andpull_request - stages: install, lint, test, security audit
Operational runbook:
docs/production-runbook.md
Minimum checklist before deployment:
- start from
.env.production.example - define strong JWT secrets (
JWT_ACCESS_SECRET,JWT_ACCESS_SECRETS) - use
DATABASE_PROVIDER=postgresqlwith a realDATABASE_URL - restrict
CORS_ALLOWED_ORIGINSto real frontend domains - run behind HTTPS/reverse proxy
Backend (Railway):
- Deploy from repository root.
- Start command:
pnpm start - Required variables:
NODE_ENV=productionPORT(provided by Railway)DATABASE_PROVIDER=postgresqlDATABASE_URL=<railway postgres url>JWT_ACCESS_ACTIVE_KID=v1JWT_ACCESS_SECRETS=v1:<strong-secret>JWT_ACCESS_SECRET=<strong-secret>CORS_ORIGIN=https://your-web-name.vercel.appCORS_ALLOWED_ORIGINS=https://your-web-name.vercel.app
Frontend (Vercel):
- Root directory:
web - Framework preset: Vite
- Build command:
npm run build - Output directory:
dist - Required variable:
VITE_API_BASE_URL=https://your-api-name.up.railway.app
Compose file: docker-compose.production.yml.
Start stack (API + PostgreSQL):
docker compose -f docker-compose.production.yml up -dFull rebuild when dependencies or Dockerfile changed:
docker compose -f docker-compose.production.yml up -d --buildStop stack:
docker compose -f docker-compose.production.yml downRecommended local flow (startup + verification):
pnpm prod:deploy:localHelper commands:
pnpm prod:up
pnpm prod:up:build
pnpm prod:up:dbport -- 55432
pnpm prod:ps
pnpm prod:smoke
pnpm prod:smoke:auth
pnpm prod:verify
pnpm prod:recovery:test
pnpm prod:down
pnpm prod:reset
pnpm perf:docker:du
pnpm perf:docker:clean
pnpm perf:docker:clean:volumes
pnpm perf:docker:maintainNotes:
prod:upavoids image rebuild by default. Useprod:up:buildonly when needed.- API container runs
pnpm prisma:bootstrap(db push) before server start to keep schema consistent. - Replace
change_mevalues with real secrets. - Prefer injecting secrets through a secret manager in managed environments.
- Set
APP_HOST_PORTin.env.productionif3000is in use. - Set
POSTGRES_HOST_PORTin.env.productionfor external DB tools (DBeaver, DataGrip, scripts). - For quick custom host port tests without editing
.env.production, usepnpm prod:up:dbport -- 55432. - Container log rotation is configured with
DOCKER_LOG_MAX_SIZEandDOCKER_LOG_MAX_FILE.
See .env.example:
NODE_ENV(development,test,production)PORT(API port)DOCKER_LOG_MAX_SIZE(max container log file size, e.g.10m)DOCKER_LOG_MAX_FILE(max number of log files per container)CORS_ORIGIN(frontend origin, e.g.http://localhost:5173)CORS_ALLOWED_ORIGINS(comma-separated allowlist)DATABASE_PROVIDER(json,mysql,postgresql,sqlite,sqlserver)DATABASE_URL(relational DB connection string; if empty, defaults are derived from provider +DB_PORT_*)POSTGRES_HOST_PORT(published PostgreSQL port on host for production compose)DB_PORT_MYSQL(default3306)DB_PORT_POSTGRESQL(default5432)DB_PORT_SQLITE(SQLite uses no network port, keep0)DB_PORT_SQLSERVER(default1433)AUTH_RATE_LIMIT_WINDOW_MINUTESAUTH_RATE_LIMIT_MAX_REQUESTSLOGIN_ATTEMPT_WINDOW_MINUTESLOGIN_MAX_FAILED_ATTEMPTSLOGIN_BLOCK_DURATION_MINUTESLOGIN_BLOCK_BACKOFF_MULTIPLIERLOGIN_MAX_BLOCK_DURATION_MINUTESCSRF_TOKEN_TTL_MINUTESJWT_ACCESS_ACTIVE_KIDJWT_ACCESS_SECRETS(kid:secret,kid2:secret2)JWT_ACCESS_SECRETACCESS_TOKEN_EXPIRES_IN(e.g.15m)REFRESH_TOKEN_TTL_DAYS
- Formatting:
prettier.config.cjs - Type checking baseline:
tsconfig.json - Monorepo-ready task graph:
turbo.json - Vitest project config:
vitest.config.mjs - Vitest workspace config:
vitest.workspace.mjs
- License:
LICENSE - Change history:
CHANGELOG.md
Base URL: http://localhost:3000
GET /openapi.jsonGET /docs
GET /health/livenessGET /health/readinessGET /health(alias for readiness)
POST /auth/registerPOST /auth/loginGET /auth/mePOST /auth/refresh-tokenPOST /auth/logout
Example register payload:
{
"name": "John Smith",
"email": "john@email.com",
"password": "StrongPass123",
"confirmPassword": "StrongPass123"
}- Progressive and persistent login lockout by IP + email
- Refresh token family rotation with reuse detection
- CSRF protection on refresh/logout
helmethardening enabled- Multi-origin CORS allowlist via
CORS_ALLOWED_ORIGINS - JWT key rotation support with
kid