Files
comparaison/docs/architecture.md

5.4 KiB

ComparAIson — Architecture

System Overview

┌─────────────┐     ┌──────────────┐     ┌─────────────┐
│   Browser    │────▶│   Traefik    │────▶│   Next.js   │
│  (React SPA) │◀────│  (Reverse    │◀────│  (Port 3000)│
│              │     │   Proxy)     │     │             │
└─────────────┘     └──────────────┘     └──────┬──────┘
                                                  │
                                    ┌─────────────┼─────────────┐
                                    ▼             ▼             ▼
                              ┌──────────┐ ┌──────────┐ ┌──────────┐
                              │PostgreSQL│ │  Tavily  │ │  OpenAI  │
                              │  (DB)    │ │ (Search) │ │  (LLM)   │
                              └──────────┘ └──────────┘ └──────────┘
                                                        ┌──────────┐
                                                        │Perplexity│
                                                        │ (LLM)    │
                                                        └──────────┘

Component Architecture

Frontend (Next.js App Router)

Route Groups:
├── (auth)/          — Unauthenticated pages (sign-in, sign-up)
├── (main)/          — Authenticated pages with shared nav layout
│   ├── compare/     — Comparison creation + results viewing
│   ├── explore/     — Public feed browsing
│   └── profile/     — User profile + comparison history
└── api/             — Server-side API routes
    ├── auth/        — Better Auth endpoints
    └── compare/     — SSE research streaming endpoint

Key patterns:

  • Server Components for data-fetching pages (profile, explore)
  • Client Components for interactive UI (compare input, charts, streaming)
  • Server Actions for mutations (save comparison, update profile)
  • SSE streaming for real-time research progress

Backend Services

Research Pipeline (src/lib/llm/)

Orchestrates the multi-stage research process:

  1. Input parsing — Validate items, extract dimensions
  2. Provider detection — Check available API keys, select best provider chain
  3. Web search — Tavily API searches per item
  4. LLM synthesis — Structured JSON generation via Perplexity or OpenAI
  5. Validation — Runtime type checking of LLM output
  6. Persistence — Store results in PostgreSQL via Drizzle ORM

Auth System (src/lib/auth.ts)

  • Better Auth with Drizzle adapter
  • Email + password authentication
  • 7-day session expiry
  • Middleware-based route protection

Database (src/lib/db/)

  • Drizzle ORM with PostgreSQL
  • 5 tables: users, sessions, comparisons, comparison_items, comparison_dimensions
  • JSONB columns for flexible research data storage
  • Indexed on userId, slug, status for query performance

Data Flow

Comparison Creation Flow

1. User enters items + query on /compare
2. Client calls POST /api/compare with { items, query, dimensions }
3. Server creates comparison record (status: "researching")
4. Server opens SSE stream to client
5. Research pipeline runs:
   a. Parsing → emits SSE "parsing" event
   b. For each item:
      - Tavily search → emits SSE "searching" event
      - Process results → emits SSE "researching" event with progress %
   c. Synthesize all data → emits SSE "synthesizing" event
   d. Validate + structure → emits SSE "complete" event with full data
6. Server persists results to comparisons + comparison_items tables
7. Client renders visualization components with result data
8. User redirected to /compare/[slug] with full results

Comparison Viewing Flow

1. User navigates to /compare/[slug]
2. Server component fetches comparison from DB by slug
3. If status === "researching": show streaming progress UI
4. If status === "completed": render full results with all viz components
5. If status === "failed": show error with retry option
6. Increment viewCount on each visit

Deployment Architecture

Docker Compose

services:
  app:        # Next.js standalone (~150-300MB RAM)
  db:         # PostgreSQL 16 Alpine (~200-400MB RAM)

Total estimated RAM: 400-800MB — fits comfortably on an 8GB Raspberry Pi.

Traefik Integration

The app is exposed via Traefik reverse proxy with:

  • HTTPS termination
  • Domain routing (e.g., comparaison.tophermayor.com)
  • Automatic SSL certificate management

Error Handling

Layer Strategy
LLM API failures 3x retry with exponential backoff
Provider unavailable Automatic fallback to next provider in chain
Invalid LLM output Runtime validation + retry with new prompt
Database errors Transaction rollback, error logged, user sees "failed" status
SSE connection lost Client auto-reconnects, polls comparison status from DB
Auth failures Redirect to sign-in with callback URL