02 — TECH STACK
Depends on: 01_ARCHITECTURE.md · Next: 03_DATABASE.md
1. Locked Stack — Phase 1
| Layer | Choice | Version Floor (2026-08-07) | Why |
|---|---|---|---|
| Runtime | Node.js Active LTS | 24.x (24.19.0) | LTS, perf, security |
| Package Manager | pnpm + Corepack | 11.20.0 | Exact pins, catalogs, speed |
| Frontend | Next.js (App Router) → React | Next 15.4.2 / React 19.1 | SSR/SSG, SEO, one codebase |
| UI | Tailwind CSS + shadcn/ui + Radix | Tailwind 4.1, shadcn latest | Design system, tokens |
| Animation | Motion (motion) |
12.x | Replaces framer-motion |
| Charts | Apache ECharts | 6.1 | Dashboards |
| Backend | Next.js Route Handlers (Phase 1) → Hono (Phase 2 optional) | Hono 4.x | No NestJS in Phase 1 — less boilerplate |
| DB | MariaDB 11.x + Prisma 6.x | MariaDB 11.4+, Prisma 6.7 | You already run it, already backed up |
| Cache/Queue | Valkey (or Redis) optional + pg-boss | Valkey 8, pg-boss 10 | Start without; add when needed |
| Search | MariaDB Full-Text (Phase 1) | — | Meilisearch later if needed |
| Auth | Better Auth 1.x | 1.6+ | Sessions, OAuth-ready, MFA-ready |
| Validation | Zod v4 (shared) | 4.0+ | Single source |
| Images | sharp | 0.34 | OG, thumbnails |
| Testing | Vitest + Playwright + supertest + k6 | Vitest 3, Playwright 1.52 | Unit/e2e/load |
| Deploy | Docker + Compose + Nginx + Coolify/Vercel | — | Oracle Linux 9 prod |
Why MariaDB not PostgreSQL? You operate MariaDB today. Backups, monitoring, failover already exist. MariaDB 11 handles 10M links + 100M clicks with proper indexing/partitions. PostgreSQL adds a second SQL to operate with zero business gain for Phase 1. Documented in
03_DATABASE.mdwith future migration path.
Alternative evaluation required: Every choice above must have Alternatives Considered in PROJECT_MEMORY.md with why it lost.
2. Exact Pinning Policy
// package.json — always exact, never ^ or ~
"dependencies": { "next": "15.4.2", "zod": "4.0.5" }
// pnpm-workspace.yaml — single source
catalog:
next: 15.4.2
zod: 4.0.5
.npmrc:save-exact=true,engine-strict=true,minimumReleaseAge=1440- Root
package.json:"packageManager": "pnpm@11.20.0"+"engines": {"node": ">=24 <25"} .nvmrc+.node-versioncommittedpnpm-lock.yamlcommitted, installs viapnpm install --frozen-lockfile
3. Dependency Governance (Freshness Law)
3.1 Before ANY pnpm add, run:
pnpm view <pkg> version time deprecated maintainers
pnpm view <pkg> dist.attestations
curl -s https://api.npmjs.org/downloads/point/last-week/<pkg> | jq .downloads
curl -s https://api.osv.dev/v1/query -d '{"package":{"name":"<pkg>","ecosystem":"npm"}}' | jq
# Check GitHub: last commit, open issues, archived?
3.2 Allow only if ALL true:
dist-tagislatest, no alpha/beta/rc- Last publish ≤12 months (foundational ≤18 months)
- Not deprecated, not archived repo
- No critical/high OSV advisories
- License in allowlist: MIT, Apache-2.0, BSD, ISC, 0BSD, BlueOak, CC-BY-4.0
- Provenance attestation preferred, publisher 2FA
3.3 After install:
pnpm install --frozen-lockfile # 0 deprecated warnings
pnpm audit --prod --audit-level=high # 0 high/critical
pnpm licenses list --prod # allowlist only
pnpm dlx knip && pnpm dlx depcheck # 0 unused
Paste clipped output into PROJECT_MEMORY.md Dependency Health Log.
4. Version Verification Ritual (Every Session)
node --version # must match pinned LTS
corepack pnpm --version
pnpm view next version && pnpm view react version && pnpm view prisma version \
&& pnpm view zod version && pnpm view better-auth version
If registry is newer → update pnpm-workspace.yaml, test, commit. Log in Health Log.
5. Toolchain
- TypeScript:
strict: true+noUncheckedIndexedAccess+exactOptionalPropertyTypes - Lint: ESLint flat + typescript-eslint +
eslint-plugin-security,--max-warnings=0 - Format: Prettier +
prettier --check - Hooks: lefthook/husky → lint-staged + typecheck + gitleaks
- CI: GitHub Actions:
install --frozen-lockfile → build → typecheck → lint → test → audit
6. Post-Delivery Freshness
Ship:
renovate.json— weekly, automerge patch/minor when CI green, dashboard.github/dependabot.yml— docker + actionsMAINTENANCE.md— 30-min monthly runbook (pnpm outdated -r → up → gates → deploy)scripts/deps-check.sh— runs §3.3, wired to weekly cron
Next: 03_DATABASE.md — MariaDB schema, indexes, migrations.