Files
clienthub/.planning/research/STACK.md
T
simone 5bf5dfce71 infra(04-00): route /c/ → /client/, Dockerfile, Gitea deploy
- Rename src/app/c/[token] → src/app/client/[token]
- Update proxy.ts, ClientRow, admin client detail with /client/ path
- Add output: "standalone" to next.config.ts for Docker build
- Add Dockerfile (multi-stage, node:20-alpine) and .dockerignore
- Push schema to Coolify Postgres via SSH tunnel (drizzle-kit push ✓)
- Update CLAUDE.md constraint 4 to reflect /client/ route
- Add Phase 4 planning artifacts (04-00, 04-RESEARCH, 04-PATTERNS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 16:12:05 +02:00

5.5 KiB
Raw Blame History

Technology Stack — ClientHub Freelancer Client Portal

Project: ClientHub (welcomeclient.iamcavalli.net) Researched: 2026-05-09 Confidence: HIGH


Core Framework

Technology Version Purpose Why
Next.js 15.x (latest stable) Full-stack app framework App Router + Server Actions replace a separate API layer. Vercel-native: no adapter needed. First-class TypeScript.
React 19.x UI rendering Bundled with Next.js. Server Components eliminate client-side waterfalls for the read-heavy client portal.
TypeScript 5.x Type safety Drizzle + Zod give end-to-end type inference from DB schema to form validation.

Why NOT Remix / SvelteKit / Astro: They work on Vercel but add unfamiliarity overhead with no gain at this scale.


Database

Technology Purpose Why
Neon (serverless Postgres) Primary database Free plan: 0.5 GB storage + 100 CU-hours/month — sufficient for 520 clients. Scales to zero between uses. Native Vercel integration that auto-injects DATABASE_URL per preview branch.
Drizzle ORM DB access + migrations Lightest-weight TS ORM. Ships drizzle-orm/neon-http serverless driver — no persistent TCP connections, works in Vercel Node and Edge runtimes for free. Schema-as-code with drizzle-kit handles migrations.

Why NOT Prisma: Needs PgBouncer or Prisma Accelerate ($) for serverless connection pooling. Drizzle's neon-http handles this natively at zero cost.

Why NOT Supabase: Adds RLS, Realtime, and Auth overhead you don't need and will have to maintain.


Authentication

Technology Purpose Why
Auth.js (next-auth) v4 Admin session management Credentials provider with a single admin account. Session stored as signed JWT cookie. No user table in DB.
Next.js Middleware (custom) Client secret-link validation Each client has a secretToken (nanoid, 21 chars) stored in DB. Middleware reads [token] path segment, validates against Neon, returns 404 on miss. Runs at the edge before any page renders.
nanoid Token generation Cryptographically secure, URL-safe, 21-char default (~126 bits of entropy). Generated once at client creation.

Auth flow summary:

  • /admin/* → Auth.js session required (single admin account)
  • /c/[token]/* → Middleware validates token against Neon, 404 on miss
  • Client pages: zero auth library overhead

UI

Technology Purpose Why
Tailwind CSS v4 Utility-first styling CSS-first configuration, zero runtime overhead.
shadcn/ui Component library Components copied into codebase (no runtime dep). Built on Radix UI (accessible). Provides: Badge, Progress, Card, Dialog, Table, Textarea, Select.
lucide-react Icons Tree-shaken, SVG-based, consistent.

Forms and Validation

Technology Purpose Why
Zod Schema validation Server-side in Server Actions + client-side with RHF resolver. Single source of truth for data shapes.
React Hook Form Admin form state Complex admin forms (client onboarding, task editing, quote builder). Client-facing pages use native <form> + Server Actions.

File Handling (v1)

None — document links stored as text fields in Postgres. Eliminates S3, CDN, and upload infrastructure from the initial build entirely.

If direct uploads needed in v2: UploadThing integrates directly with Next.js App Router, free tier (2 GB storage).


Infrastructure

Technology Purpose Why
Vercel Hobby plan Deploy + CDN + serverless Native Next.js. Custom subdomain (welcomeclient.iamcavalli.net) via DNS CNAME. No Docker, VPS, or CI/CD to manage.
Neon Vercel Integration DB branch per preview Creates a fresh Neon branch per Git branch automatically. Safe schema migration testing.

Installation Sequence

# 1. Bootstrap Next.js
npx create-next-app@latest clienthub --typescript --tailwind --app --src-dir

# 2. Database
npm install drizzle-orm @neondatabase/serverless
npm install -D drizzle-kit

# 3. Auth
npm install next-auth

# 4. Token generation
npm install nanoid

# 5. Validation + Forms
npm install zod @hookform/resolvers react-hook-form

# 6. shadcn/ui
npx shadcn@latest init
npx shadcn@latest add badge button card dialog dropdown-menu input label progress select separator table textarea

Key Architectural Decisions

  1. Secret-link without Auth.js: Next.js Middleware validates [token] at the edge. Fast, zero client-side JS, 404 on invalid token.
  2. Server Actions for all mutations: Task updates, comments, payment status — no REST API layer to maintain.
  3. Privacy model is a DB query filter: Admin sees quote_items; clients see only clients.accepted_total. Not a UI filter — a DB design.
  4. Two auth systems, zero overlap: Admin JWT cookie on /admin/*. Client token middleware on /c/*.

Confidence Levels

Area Confidence Notes
Next.js App Router HIGH Stable since Oct 2024
Neon free tier HIGH 0.5 GB storage, 100 CU-hours/month
Drizzle + neon-http HIGH Free serverless driver, no connection pooling needed
Auth.js Credentials (admin) HIGH Mature, well-documented
nanoid secret tokens HIGH Cryptographically secure default
Tailwind v4 + Next.js HIGH Stable, PostCSS plugin verified
Vercel Hobby plan HIGH Custom subdomain supported