System Overview¶
High-Level Architecture¶
flowchart TB
subgraph ClientLayer["Client Layer"]
Browser["Web Browser<br/>Dashboard | Documents | Photos"]
end
subgraph FrontendLayer["Frontend Layer - Next.js 14"]
subgraph Pages["Pages (App Router)"]
P1["Dashboard<br/>Synthesis previews"]
P2["Properties<br/>Inline editing"]
P3["Documents<br/>Multi-phase processing"]
P4["Photos<br/>Redesign + promote"]
end
subgraph Components["Reusable Components"]
C1["Header / Navigation"]
C2["Design System (ui/)"]
C3["Charts (Custom SVG)"]
C4["Forms & Tooltips"]
end
subgraph APIClient["API Client"]
AC1["React Query<br/>Data fetching & caching"]
AC2["TypeScript Types<br/>Type-safe API calls"]
end
end
subgraph BackendLayer["Backend Layer - FastAPI"]
subgraph Endpoints["API Endpoints"]
E1["/api/users<br/>Auth & profiles"]
E2["/api/properties<br/>CRUD + with-synthesis"]
E3["/api/documents<br/>Upload, bulk ops, synthesis"]
E4["/api/analysis<br/>Price trends"]
E5["/api/photos<br/>Redesign + promote"]
end
subgraph Services["Service Layer"]
S1["AI Services<br/>Native PDF | Thinking | Synthesis"]
S2["Storage Service<br/>MinIO | GCS abstraction"]
S3["DVF Service<br/>4.8M sales + 13.5M lots"]
S4["Price Analysis<br/>Trends & projections"]
end
end
subgraph DataLayer["Data Layer"]
PostgreSQL[("PostgreSQL 15<br/>Users | Properties<br/>Documents | DVF")]
Redis[("Redis 7<br/>Cache | Sessions")]
Storage[("Object Storage<br/>MinIO / GCS")]
end
subgraph ExternalLayer["External Services"]
Gemini["Google Gemini<br/>Vertex AI"]
end
Browser --> FrontendLayer
FrontendLayer -->|"REST API"| BackendLayer
Services --> PostgreSQL
Services --> Redis
Services --> Storage
S1 --> Gemini
Component Details¶
Frontend Architecture¶
flowchart LR
subgraph NextJS["Next.js 14 App"]
subgraph AppRouter["App Router"]
Layout["Root Layout"]
Locale["[locale] Layout"]
Pages["Page Components"]
end
subgraph Auth["Authentication"]
BetterAuth["Better Auth<br/>(API Routes)"]
AuthContext["Auth Context"]
end
subgraph State["State Management"]
ReactQuery["React Query Cache"]
i18n["next-intl<br/>FR / EN"]
end
subgraph UI["UI Layer"]
Tailwind["Tailwind CSS"]
Components["Component Library"]
end
end
Layout --> Locale --> Pages
Pages --> Auth
Pages --> State
Pages --> UI
| Directory | Purpose |
|---|---|
src/app/[locale]/ |
Locale-scoped App Router pages |
src/app/api/auth/ |
Better Auth API route handler |
src/components/ |
Reusable React components (includes ui/ design system) |
src/contexts/ |
React context providers (Auth) |
src/i18n/ |
Internationalization config and routing |
src/lib/ |
Utilities, API client, and auth config |
src/types/ |
TypeScript type definitions |
messages/ |
Translation files (en.json, fr.json) |
Key Technologies:
- React 18 with Server Components
- Better Auth for authentication (email/password + Google OAuth)
- next-intl for internationalization (FR/EN)
- Tailwind CSS with semantic design tokens for styling
- Lucide React for icons
- React Query for data fetching and caching
- TypeScript for type safety
- pnpm for package management
Backend Architecture¶
flowchart TB
subgraph FastAPI["FastAPI Application"]
subgraph Core["Core"]
Config["Configuration"]
DB["Database Session"]
Security["Auth & Security"]
end
subgraph API["API Layer"]
Routes["Route Handlers"]
Schemas["Pydantic Schemas"]
end
subgraph ServiceLayer["Services"]
AI["AI Services"]
Storage["Storage Service"]
DVF["DVF Service"]
Analysis["Price Analysis"]
end
subgraph Models["Data Models"]
ORM["SQLAlchemy Models"]
end
end
Routes --> Schemas
Routes --> ServiceLayer
ServiceLayer --> Models
ServiceLayer --> Core
Models --> DB
| Directory | Purpose |
|---|---|
app/api/ |
REST API route handlers |
app/core/ |
Configuration, database, security |
app/models/ |
SQLAlchemy ORM models |
app/schemas/ |
Pydantic request/response schemas |
app/services/ |
Business logic and integrations |
app/prompts/ |
AI prompt templates (versioned) |
Key Technologies:
- FastAPI for async HTTP handling
- SQLAlchemy 2.0 for ORM
- Pydantic v2 for validation
- Google Generative AI SDK (
google-genai) for Gemini (Vertex AI or REST API) - UV for fast package management
Data Layer¶
flowchart LR
subgraph PostgreSQL["PostgreSQL 15"]
Users["users"]
Properties["properties"]
Documents["documents"]
DVF["dvf_sales (4.8M)<br/>dvf_sale_lots (13.5M)"]
end
subgraph Redis["Redis 7"]
Sessions["Session Store"]
Cache["Query Cache"]
RateLimit["Rate Limiting"]
end
subgraph ObjectStorage["Object Storage"]
DocBucket["documents/"]
PhotoBucket["photos/"]
end
PostgreSQL¶
Stores structured data:
| Table | Records | Purpose |
|---|---|---|
users |
~100s | User accounts and profile data |
ba_user |
~100s | Better Auth user accounts |
ba_session |
~100s | Better Auth active sessions |
ba_account |
~100s | Better Auth OAuth provider links |
properties |
~100s | Properties and their metadata |
documents |
~1000s | Documents and analysis results (5 categories) |
document_summaries |
~100s | Cross-document synthesis with user overrides |
price_analyses |
~100s | Cached DVF price analysis results |
dvf_sales |
4.8M | French property transactions (2015-2025) |
dvf_sale_lots |
13.5M | Individual lots within transactions |
Redis¶
In-memory caching for:
- Session data (7-day TTL)
- Frequently accessed queries (1-hour TTL)
- Rate limiting counters
- API response caching via
app/core/cache.py(fault-tolerant -- Redis down = cache miss, never an error): - DVF stats:
dvf_statskey, 1h TTL - Price analysis summary:
price_analysis_summary:{id}, 30min TTL - Price analysis full:
price_analysis_full:{id}, 30min TTL
Object Storage (MinIO / GCS)¶
File storage for:
- Uploaded documents (PDFs, images)
- Generated images (photo redesigns)
- Presigned URLs for secure browser access
Service Dependencies¶
graph TD
subgraph Application["Application Services"]
Frontend["Frontend<br/>Next.js"]
Backend["Backend<br/>FastAPI"]
end
subgraph Data["Data Services"]
PostgreSQL[("PostgreSQL")]
Redis[("Redis")]
Storage[("MinIO/GCS")]
end
subgraph External["External Services"]
Gemini["Gemini AI<br/>Vertex AI"]
end
Frontend -->|"HTTP/REST"| Backend
Backend -->|"SQL"| PostgreSQL
Backend -->|"Cache"| Redis
Backend -->|"Files"| Storage
Backend -->|"AI API"| Gemini
Security Architecture¶
Authentication Flow (Better Auth)¶
Authentication is handled by Better Auth on the frontend via Next.js API routes. The backend validates sessions by checking cookies against the ba_session database table.
sequenceDiagram
participant User as User Browser
participant FE as Frontend (Next.js)
participant Auth as API Route (/api/auth/*)
participant DB as PostgreSQL
participant BE as Backend (FastAPI)
rect rgb(230, 245, 255)
Note over User,DB: Registration / Login
User->>FE: 1. Enter credentials (or click Google OAuth)
FE->>Auth: 2. POST /api/auth/sign-in
Auth->>DB: 3. Verify credentials (bcrypt)
Auth->>DB: 4. Create session in ba_session table
Auth-->>FE: 5. Set HTTP-only cookie (better-auth.session_token)
FE-->>User: 6. Redirect to dashboard
end
rect rgb(230, 255, 230)
Note over User,BE: Authenticated API Requests
User->>FE: 7. Access protected page
FE->>BE: 8. Request with session cookie
BE->>DB: 9. Validate cookie against ba_session
BE->>DB: 10. Check session expiry + user active
BE-->>FE: 11. Return protected data
FE-->>User: 12. Display content
end
Key differences from legacy JWT:
- No tokens stored in localStorage — HTTP-only cookies only
- Session state lives in PostgreSQL (
ba_sessiontable), not in the token - Google OAuth supported as an optional provider
- Backend validates by querying the database, not by verifying a JWT signature
Security Layers¶
flowchart TB
subgraph Edge["Edge Security"]
HTTPS["HTTPS/TLS 1.3"]
CORS["CORS Policy"]
end
subgraph App["Application Security"]
Auth["Better Auth Sessions<br/>(HTTP-only cookies)"]
Validation["Input Validation<br/>Pydantic"]
SQLi["SQL Injection Prevention<br/>SQLAlchemy"]
end
subgraph Data["Data Security"]
Encryption["Encryption at Rest"]
PrivateNet["Private Networking"]
IAM["IAM / Service Accounts"]
end
HTTPS --> CORS
CORS --> Auth
Auth --> Validation
Validation --> SQLi
SQLi --> Encryption
Encryption --> PrivateNet
API Security¶
| Layer | Protection |
|---|---|
| Transport | HTTPS with TLS 1.3 |
| Origin | CORS restricted to allowed origins |
| Rate Limiting | Redis-based request throttling |
| Authentication | Better Auth session cookies (7-day expiry) |
| Authorization | Role-based access control |
| Input | Pydantic schema validation |
| Database | SQLAlchemy parameterized queries |
Storage Security¶
| Environment | Authentication | Access Control |
|---|---|---|
| Local (MinIO) | Access keys | Bucket policies |
| Production (GCS) | Service account | IAM roles |
| Browser Access | Presigned URLs | Time-limited (15 min) |
Deployment Architecture¶
Local Development¶
flowchart TB
subgraph Docker["Docker Compose"]
FE["frontend:3000"]
BE["backend:8000"]
DB["postgres:5432"]
REDIS["redis:6379"]
MINIO["minio:9000/9001"]
end
FE --> BE
BE --> DB
BE --> REDIS
BE --> MINIO
Production (GCP)¶
flowchart TB
subgraph Internet
Users["Users"]
DNS["DNS"]
end
subgraph GCP["Google Cloud Platform"]
LB["Load Balancer<br/>+ Managed SSL"]
subgraph CloudRun["Cloud Run"]
FE["Frontend Service"]
BE["Backend Service"]
end
subgraph Private["Private Network"]
SQL["Cloud SQL"]
Redis["Memorystore"]
end
GCS["Cloud Storage"]
Vertex["Vertex AI"]
end
Users --> DNS
DNS --> LB
LB --> FE
LB --> BE
BE --> SQL
BE --> Redis
BE --> GCS
BE --> Vertex
Technology Stack Summary¶
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 14 | React framework with App Router |
| TypeScript | Type safety | |
| Tailwind CSS | Utility-first styling | |
| React Query | Data fetching & caching | |
| pnpm | Package management | |
| Backend | FastAPI | Async Python web framework |
| SQLAlchemy 2.0 | ORM | |
| Pydantic v2 | Data validation | |
| UV | Fast package management | |
| AI | Google Gemini | Multimodal AI (vision + text) |
| Vertex AI | Managed AI platform | |
| Database | PostgreSQL 15 | Primary data store |
| Redis 7 | Caching & sessions | |
| Storage | MinIO | Local S3-compatible storage |
| Google Cloud Storage | Production file storage | |
| Infrastructure | Docker | Containerization |
| Terraform | Infrastructure as Code | |
| GCP Cloud Run | Serverless containers |