An opinionated full-stack SaaS template for teams that want to start from a hardened, reusable product baseline instead of rebuilding the same infrastructure on every project.
apps/web: Next.js 15 App Router, Tailwind, shared UI package, nonce-based CSP with staged report-only rollout support, strict browser security headers, and server-side/api/*proxyingapps/api: NestJS 11, Prisma, Postgres, Swagger, session-cookie auth, CSRF protection, idempotency, RBAC, rate limiting, audit loggingapps/api: enterprise identity support with OIDC-first login, optional SAML and SCIM, break-glass login, and owner step-up confirmationapps/api: Prometheus-compatible metrics at/api/metricswith optional OTLP tracing behindFEATURE_OBSERVABILITYpackages/contracts: shared ts-rest contract router for website-facing API callspackages/db: shared Prisma schema, migrations, seed flowpackages/shared: shared Zod contracts and DTO typespackages/ui: reusable UI primitives and styling helperspackages/config: shared ESLint, Prettier, and TypeScript config
- email/password signup, login, logout, logout-all, session revocation, forgot-password, and reset-password flows
- single-tenant roles:
owner,admin, andmember - authenticated dashboard shell with profile settings, session security, and admin user management
- Projects reference slice with indexed search, filters, cursor pagination, ownership-aware mutations, detail/edit, archive, delete, and streamed CSV export
- Docker-first local stack with Next.js, NestJS, and Postgres
- optional observability profiles for Prometheus and Grafana
- real lint, typecheck, unit tests, API integration tests, and Playwright auth/project/session/RBAC coverage
- DB-backed bootstrap ownership state and owner-floor role protection for concurrent admin changes
- markdown lint, internal doc-link validation, and k6 performance assets for auth/session/write-heavy flows
- browser-boundary hardening with CSP, clickjacking protection, strict cookie forwarding, route-level forbidden/error states, and role-aware admin navigation
- contract-backed web/API calls through
packages/contractswith runtime Zod validation for JSON responses and explicit non-JSON handling for export/download paths - accessible auth forms with polite live error regions and field-level associations
- CI, Docker image publishing workflow, and CodeQL scanning
- enterprise SSO, optional SCIM provisioning, retention-aware governance cleanup, Kubernetes deployment baseline, and release-integrity workflows for SBOM, dependency review, image scanning, signing, and provenance
Copy-Item .env.example .env
npm install
npm run dev:services
npm run db:setup
npm run devOpen:
- web:
http://localhost:3000 - API docs:
http://localhost:4000/api/docs - health:
http://localhost:4000/api/health
Seeded owner credentials come from .env:
- email:
owner@example.com - password:
ChangeMe123!
APP_ENV is the deployment-security axis:
localfor developer machinestestfor automated test harnessesstagingandproductionfor strict deploy targets
Local-only toggles such as ALLOW_MISSING_ORIGIN_FOR_DEV and EXPOSE_DEV_RESET_DETAILS now fail fast outside their allowed environments.
Copy-Item .env.example .env
docker compose up --buildThe Compose stack starts Postgres, runs migrations and seeding in the API container, then serves:
- web on
http://localhost:3000 - API on
http://localhost:4000
If you run the repo from WSL, use Linux shell commands inside WSL and make sure Docker Desktop has WSL integration enabled for your distro. Typical flow:
cp .env.example .env
docker compose up --buildnpm run dev: start web and API in watch modenpm run dev:services: start Postgres onlynpm run db:setup: run local migrations and seed datanpm run db:reset: reset the database and reseed itnpm run lint: run ESLint and Prisma validationnpm run typecheck: run TypeScript and Prisma validationnpm test: run workspace Vitest suitesnpm run test:e2e: run the full Playwright E2E suitenpm run test:e2e:enterprise: run the enterprise-login Playwright smoke under the OIDC-first enterprise profilenpm run docs:check: run markdown lint and internal link validationnpm run test:perf:smoke: run the smoke-level k6 performance scenarionpm run test:perf:critical: run the deeper critical auth/session/project API performance scenarionpm run perf:up: start the Compose stack with the local perf env overlay for K6 runsnpm run perf:down: stop the local perf stacknpm run build: produce production builds for every workspacenpm run docker:up: build and start the Compose stacknpm run docker:down: stop and clean up Compose containers
apps/
api/ NestJS API
web/ Next.js application
packages/
config/ Shared ESLint, Prettier, and TS config
contracts/ ts-rest API contract package
db/ Prisma schema, migrations, seed script
shared/ Zod schemas and shared DTO types
ui/ Reusable UI primitives
vendor/
nestjs-config/ Temporary vendored @nestjs/config security patch
nestjs-swagger/ Temporary vendored @nestjs/swagger security patch
docs/
architecture.md
code-critique.md
reference-baseline.md
environment.md
local-development.md
deployment.md
contracts.md
web-hardening.md
testing-and-failpoints.md
template-conventions.md
customization-checklist.md
infra/
compose/ Optional extension services
k8s/ Kubernetes production baseline
scripts/
with-env.mjs Shared env loader for workspace commands
The default template keeps the runtime small: web, API, and Postgres only. Optional extension services live in infra/compose/docker-compose.extensions.yml and stay off by default.
cache: Redisemail: Mailpitstorage: MinIOedge: Nginx reverse proxy
- Reference Baseline
- Architecture
- Code Critique
- Environment Catalog
- Local Development Runbook
- Migrations
- Deployment Runbook
- API Contract Guide
- Enterprise Identity Guide
- Governance And Compliance Guide
- Control And Evidence Matrix
- Kubernetes Deployment Baseline
- Web Hardening Guide
- Testing And Failpoint Guide
- Operations Guide
- Template Conventions
- ADR 001
- ADR 002
- ADR 003
- ADR 004
- Customization Checklist
This template was shaped against a private research archive of open-source repositories, official documentation, and public issue discussions, not copied from a single starter. The public provenance map of direct donors, validation references, and intentionally unadopted patterns is in Reference Baseline.
The repo currently vendors patched copies of @nestjs/config and
@nestjs/swagger under vendor/ because their published manifests still pin
vulnerable transitive versions of lodash and path-to-regexp. Only package
manifests were changed; runtime code remains the upstream package build output.
See vendor/README.md for the exact patched dependencies
and remove the vendored copies once upstream publishes equivalent fixes.
This repository is source-available under the terms in LICENSE.
- personal, self-study, research, classroom, and academic use are allowed
- commercial, entrepreneurial, startup, agency, client, or corporate use requires prior written permission
- vendored third-party materials remain under their own upstream licenses
See:
This project is developed in a personal capacity; affiliations do not imply endorsement by Stellenbosch University.
External code contributions require agreement to the repository CLA before merge.