Files
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

132 lines
5.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Technology Stack — ClientHub Freelancer Client Portal
**Project:** ClientHub (welcomeclient.iamcavalli.net)
**Researched:** 2026-05-09
**Confidence:** HIGH
---
## Recommended Stack
### 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
```bash
# 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 |