Files
tessera-ctl/.planning/research/STACK.md
T
schalli 16c2d5b6af 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>
2026-06-18 08:28:58 +02:00

12 KiB

Technology Stack

Project: Tessera - Modular Portal Platform with Marketplace Researched: 2026-06-18 Overall Confidence: HIGH

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

# 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)

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