docs: complete project research for Tessera portal platform
Synthesize stack, features, architecture, and pitfalls research into unified summary with roadmap implications and phase suggestions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
# Technology Stack
|
||||
|
||||
**Project:** Tessera - Modular Portal Platform with Marketplace
|
||||
**Researched:** 2026-06-18
|
||||
**Overall Confidence:** HIGH
|
||||
|
||||
## Recommended Stack
|
||||
|
||||
### Monorepo & Package Management
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| pnpm | 9.x | Package manager | 60-80% disk reduction via content-addressable store, strict dependency isolation prevents phantom deps, workspace protocol for internal packages |
|
||||
| Turborepo | 2.9.x | Build orchestration | Incremental builds, parallel execution, task dependency graph, caching. Vercel-maintained — aligns with Next.js ecosystem |
|
||||
|
||||
**Monorepo Structure:**
|
||||
```
|
||||
tessera/
|
||||
apps/
|
||||
web/ # Next.js 16 frontend
|
||||
api/ # NestJS backend
|
||||
desktop/ # Tauri desktop wrapper
|
||||
packages/
|
||||
shared/ # Shared types, DTOs, constants
|
||||
ui/ # Shared UI components (shadcn-based)
|
||||
config/ # ESLint, TypeScript, Tailwind configs
|
||||
db/ # Prisma schema & client
|
||||
```
|
||||
|
||||
**Why Turborepo over Nx:** Turborepo is simpler, zero-config for most cases, and aligns with Vercel/Next.js tooling. Nx is more powerful for massive enterprise repos but adds unnecessary complexity for a team building with Claude.
|
||||
|
||||
### Frontend
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Next.js | 16.2.x | Frontend framework | App Router with React 19, Turbopack default bundler (4x faster builds), stable Server Components, `use cache` directive, multi-tenant middleware support |
|
||||
| React | 19.x | UI library | Ships with Next.js 16, React Compiler (automatic memoization), stable Server Actions |
|
||||
| TypeScript | 5.5+ | Type safety | Required by all major tools, catches bugs at compile time |
|
||||
| Tailwind CSS | 4.3.x | Styling | CSS-first config (no JS config file), 3.5x faster rebuilds, OKLCH colors, built-in dark mode via `.dark` selector |
|
||||
| shadcn/ui | CLI v4 | Component library | Not a dependency — copies components into your project. Accessible, themeable via CSS variables, dark/light mode trivial with next-themes. Dashboard-ready components |
|
||||
| next-themes | 0.4.x | Theme switching | 2-line dark mode integration with shadcn/ui, SSR-safe, system preference detection |
|
||||
| next-intl | 4.13.x | Internationalization | Built for Next.js App Router, Server Component native, 457 bytes gzipped, simpler than i18next for Next.js-only projects |
|
||||
| react-grid-layout | 2.2.x | Dashboard grid | TypeScript rewrite with hooks API (useGridLayout, useResponsiveLayout), drag & drop + resize, responsive breakpoints, 100% backward compat via /legacy |
|
||||
| Zustand | 5.0.x | Client state | Lightweight (1.1kb), no providers needed, works with Server Components, perfect for UI state (sidebar toggle, theme, user prefs) |
|
||||
| TanStack Query | 5.101.x | Server state | Caching, background refresh, optimistic updates, pagination. Use for client-side data fetching where Server Components don't suffice |
|
||||
|
||||
### Backend
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| NestJS | 11.x | API framework | Modular architecture maps directly to Tessera's module system. Dependency injection, guards, interceptors, built-in microservices support. Modular monolith now, extract to microservices later if needed |
|
||||
| Express | 5.x | HTTP server | Default in NestJS 11, battle-tested, massive middleware ecosystem |
|
||||
| Prisma | 7.8.x | ORM | TypeScript-first, auto-generated types from schema, declarative migrations, Client Extensions for RLS multi-tenancy. v7 dropped Rust engine — 3x faster queries, 90% smaller bundles |
|
||||
| PostgreSQL | 16.x | Database | Row-Level Security for multi-tenancy, JSONB for flexible module config, excellent Docker support, robust at any scale |
|
||||
| Redis | 7.x | Cache & sessions | Session storage, pub/sub for real-time features, rate limiting, cache invalidation |
|
||||
|
||||
### Authentication & Authorization
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Keycloak | 26.6.x | Identity provider | Native multi-tenancy via realms, LDAP/AD federation built-in, OAuth2/OIDC standard, Docker-native, admin UI included. Eliminates building auth from scratch |
|
||||
| nest-keycloak-connect | latest | NestJS integration | Guards, decorators, multi-tenant realm resolvers — handles JWT validation and role extraction |
|
||||
| @nestjs/passport | latest | Fallback auth | For API key auth on module-to-module communication |
|
||||
|
||||
**Why Keycloak over custom auth:** The project requires LDAP integration, multi-tenancy, admin user management, and token-based auth. Building this from scratch would take weeks and introduce security vulnerabilities. Keycloak provides all of this as a Docker container with zero custom code.
|
||||
|
||||
### Desktop Wrapper
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Tauri | 2.x (2.11+) | Desktop app | 5MB installer vs Electron's 150MB. Uses OS-native WebView — no bundled Chromium. Rust backend for system APIs. Windows + Linux supported. Perfect for wrapping an existing web app |
|
||||
|
||||
**Why Tauri over Electron:** Tessera's desktop client is a thin wrapper around the web portal — it does not need Node.js APIs, multi-window workflows, or pixel-perfect cross-platform rendering. Tauri's 96% smaller bundle size, 30-50MB memory usage (vs 150-300MB), and native performance make it the clear choice for a web-app wrapper. The user is not a programmer, so less moving parts (no Node.js backend process) is better.
|
||||
|
||||
**Trade-off acknowledged:** Tauri uses the OS WebView (WebView2 on Windows, webkit2gtk on Linux), so minor rendering differences may exist. For an internal tool this is acceptable.
|
||||
|
||||
### Infrastructure & DevOps
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Docker | 27.x | Containerization | Project constraint. Multi-stage builds for production images |
|
||||
| Docker Compose | 2.x | Orchestration | Multi-service local dev and production deployment. Health checks, volume management, networking |
|
||||
| Traefik | 3.x | Reverse proxy | Automatic SSL, Docker-native service discovery, routing rules via labels. Simpler than nginx for Docker-compose setups |
|
||||
| Gitea | existing | Version control | Already in place. Automate via webhooks and Gitea API |
|
||||
|
||||
### Testing
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Vitest | 3.x | Unit/integration tests | Fast, ESM-native, compatible with Jest API, works with both Next.js and NestJS |
|
||||
| Playwright | 1.x | E2E tests | Cross-browser, auto-wait, trace viewer. Best for testing the full portal flow |
|
||||
| Testing Library | latest | Component tests | DOM-based testing, framework-agnostic patterns |
|
||||
|
||||
### Developer Experience
|
||||
|
||||
| Technology | Version | Purpose | Why |
|
||||
|------------|---------|---------|-----|
|
||||
| Biome | 2.x | Linting + formatting | Single tool replaces ESLint + Prettier, 100x faster, zero-config defaults. Reduces tooling complexity |
|
||||
| Husky | 9.x | Git hooks | Pre-commit formatting/linting enforcement |
|
||||
| lint-staged | 15.x | Staged file linting | Only lint changed files for fast commits |
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
| Category | Recommended | Alternative | Why Not |
|
||||
|----------|-------------|-------------|---------|
|
||||
| Frontend Framework | Next.js 16 | Remix / SvelteKit | Next.js has best multi-tenant support, largest ecosystem, Vercel Platforms template as reference |
|
||||
| Backend Framework | NestJS 11 | Fastify standalone / Express | NestJS module system maps perfectly to Tessera modules. DI, guards, and interceptors reduce boilerplate |
|
||||
| ORM | Prisma 7 | Drizzle ORM | Prisma has gentler learning curve (built by Claude, non-programmer user), better migration safety. Drizzle is faster in serverless (irrelevant here — Docker deployment) |
|
||||
| Database | PostgreSQL 16 | MariaDB | PostgreSQL has native RLS for multi-tenancy, superior JSONB support, better extension ecosystem |
|
||||
| Auth | Keycloak | Custom JWT + LDAP lib | Building LDAP + multi-tenant auth from scratch is weeks of work and a security risk |
|
||||
| Desktop | Tauri 2 | Electron | 96% smaller, 5x less memory. Tessera desktop is a wrapper, not a full desktop app |
|
||||
| State | Zustand | Redux Toolkit | Zustand is 7x smaller bundle, no boilerplate, no providers. Redux is overkill for this project |
|
||||
| i18n | next-intl | react-i18next | next-intl is built for App Router, Server Component native, simpler API |
|
||||
| CSS | Tailwind 4 | CSS Modules / Styled Components | Utility-first is faster to develop, dark mode trivial, shadcn/ui requires it |
|
||||
| Package Manager | pnpm | npm / yarn | pnpm has strict isolation, better disk usage, workspace support built-in |
|
||||
| Monorepo Tool | Turborepo | Nx | Turborepo is simpler, aligns with Vercel ecosystem, sufficient for this project size |
|
||||
| Linting | Biome | ESLint + Prettier | Single tool, 100x faster, less config. ESLint is being replaced in NestJS 12 roadmap anyway |
|
||||
| Component Library | shadcn/ui | Material UI / Ant Design | shadcn gives ownership of components (no dep lock-in), built on Radix primitives, Tailwind-native |
|
||||
| Dashboard Grid | react-grid-layout | Gridstack.js | React-native, TypeScript rewrite in v2, hooks API, responsive breakpoints |
|
||||
| Reverse Proxy | Traefik | nginx | Docker-native service discovery, auto-SSL, config via labels not files |
|
||||
|
||||
## Multi-Tenancy Strategy
|
||||
|
||||
**Approach:** Shared schema with Row-Level Security (RLS) in PostgreSQL.
|
||||
|
||||
**Why RLS over schema-per-tenant:**
|
||||
- Scales to thousands of tenants without catalog bloat
|
||||
- Single connection pool (no per-tenant connection overhead)
|
||||
- Prisma Client Extensions support RLS via session variables
|
||||
- Simpler migrations — one schema to manage
|
||||
- Cost-effective for the planned growth trajectory
|
||||
|
||||
**Implementation:**
|
||||
1. Every tenant table has a `tenant_id` column
|
||||
2. RLS policies enforce `WHERE tenant_id = current_setting('app.tenant_id')`
|
||||
3. NestJS middleware sets the tenant context on every request
|
||||
4. Prisma Client Extension wraps queries with `SET app.tenant_id`
|
||||
5. Keycloak realm maps to tenant, JWT contains tenant_id claim
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Initialize monorepo
|
||||
pnpm create turbo@latest tessera --example basic
|
||||
|
||||
# Frontend (apps/web)
|
||||
pnpm add next@16 react@19 react-dom@19
|
||||
pnpm add next-intl@4 next-themes zustand@5 @tanstack/react-query@5
|
||||
pnpm add react-grid-layout@2
|
||||
pnpm add -D tailwindcss@4 @tailwindcss/postcss typescript @types/react
|
||||
|
||||
# Backend (apps/api)
|
||||
pnpm add @nestjs/core@11 @nestjs/common@11 @nestjs/platform-express@11
|
||||
pnpm add @nestjs/config @nestjs/jwt @nestjs/passport
|
||||
pnpm add nest-keycloak-connect
|
||||
pnpm add @prisma/client@7 ioredis
|
||||
pnpm add -D prisma@7 @nestjs/cli@11
|
||||
|
||||
# Desktop (apps/desktop)
|
||||
# Tauri CLI installed via cargo or npm
|
||||
pnpm add -D @tauri-apps/cli@2
|
||||
|
||||
# Shared (packages/shared)
|
||||
# Types, DTOs, and constants — no runtime deps
|
||||
|
||||
# Dev tools (root)
|
||||
pnpm add -D turbo@2 @biomejs/biome@2 husky@9 lint-staged@15
|
||||
pnpm add -D vitest@3 @playwright/test
|
||||
```
|
||||
|
||||
## Docker Services (docker-compose.yml)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
web: # Next.js frontend (port 3000)
|
||||
api: # NestJS backend (port 3001)
|
||||
db: # PostgreSQL 16 (port 5432)
|
||||
redis: # Redis 7 (port 6379)
|
||||
keycloak: # Keycloak 26.6.x (port 8080)
|
||||
traefik: # Reverse proxy (port 80/443)
|
||||
```
|
||||
|
||||
## Version Pinning Strategy
|
||||
|
||||
- **Major versions:** Pin to major (e.g., `next@16`, `@nestjs/core@11`)
|
||||
- **Prisma:** Pin exactly — schema changes require matched versions
|
||||
- **Tailwind/shadcn:** Follow latest within major — utility additions are non-breaking
|
||||
- **Keycloak Docker image:** Pin to minor (e.g., `quay.io/keycloak/keycloak:26.6`)
|
||||
|
||||
## Sources
|
||||
|
||||
- [Next.js 16 Docs](https://nextjs.org/docs/app/guides/upgrading/version-16) — Version 16.2.7+ stable
|
||||
- [NestJS Documentation](https://docs.nestjs.com/) — Version 11.1.x
|
||||
- [Prisma ORM 7 Announcement](https://www.prisma.io/blog/announcing-prisma-orm-7-0-0) — Pure TypeScript runtime
|
||||
- [Tauri 2.0 Stable Release](https://v2.tauri.app/blog/tauri-20/) — Cross-platform desktop
|
||||
- [Keycloak 26.6 Release](https://www.keycloak.org/2026/04/keycloak-2660-released) — Latest stable
|
||||
- [Turborepo](https://turborepo.dev/) — Version 2.9.x
|
||||
- [shadcn/ui CLI v4](https://ui.shadcn.com/docs/changelog/2026-03-cli-v4) — March 2026 update
|
||||
- [Tailwind CSS v4.3](https://tailwindcss.com/blog/tailwindcss-v4-3) — Latest features
|
||||
- [next-intl](https://next-intl.dev/) — Version 4.13.x
|
||||
- [react-grid-layout](https://github.com/react-grid-layout/react-grid-layout) — Version 2.2.x TypeScript rewrite
|
||||
- [PostgreSQL RLS Multi-Tenancy](https://aws.amazon.com/blogs/database/multi-tenant-data-isolation-with-postgresql-row-level-security/)
|
||||
- [pnpm Workspaces](https://pnpm.io/workspaces) — Workspace management
|
||||
Reference in New Issue
Block a user