# Design: Multi-Theme Synthesis Support **Date**: 2026-03-26 **Scope**: Allow users to create multiple themes, each with its own content settings and sources, generating syntheses per theme. --- ## Context Currently each user has a single theme with one set of categories. Users who follow multiple topics (e.g. AI + Cybersecurity) must choose one or regenerate with different settings. This feature adds support for multiple themes per user. --- ## 1. Data Model ### New table: `themes` ```sql CREATE TABLE themes ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, name TEXT NOT NULL, theme TEXT NOT NULL, categories JSONB NOT NULL DEFAULT '[]', max_items_per_category INTEGER NOT NULL DEFAULT 4, max_age_days INTEGER NOT NULL DEFAULT 7, summary_length INTEGER NOT NULL DEFAULT 3, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_themes_user_id ON themes(user_id); ``` ### Modified table: `sources` Add `theme_id UUID REFERENCES themes(id) ON DELETE CASCADE`. Sources become per-theme. ### Modified table: `syntheses` Add `theme_id UUID REFERENCES themes(id) ON DELETE SET NULL`. Links each synthesis to its theme. `SET NULL` preserves syntheses when a theme is deleted. ### Modified table: `settings` Remove columns that move to `themes`: `theme`, `categories`, `max_items_per_category`, `max_age_days`, `summary_length`. ### Migration strategy 1. Create `themes` table 2. For each user with settings, create a default theme from their current content settings 3. Add `theme_id` to `sources`, populate with the user's default theme 4. Add `theme_id` to `syntheses`, populate with the user's default theme 5. Drop moved columns from `settings` --- ## 2. Backend API ### New endpoints — Themes CRUD - `GET /api/v1/themes` — list user's themes - `POST /api/v1/themes` — create a new theme - `PUT /api/v1/themes/:id` — update a theme - `DELETE /api/v1/themes/:id` — delete a theme (syntheses kept with `theme_id = NULL`) ### Modified endpoints - `GET /api/v1/sources` — add optional `?theme_id=` filter - `POST /api/v1/sources` — require `theme_id` in request body - `POST /api/v1/syntheses/generate` — require `theme_id` in request body - `GET /api/v1/syntheses` — response includes `theme_name`. Add optional `?sort=date|theme` param. ### Pipeline change `run_generation_inner` receives `theme_id` and loads content settings (theme, categories, max_items, max_age, summary_length) from the `themes` table instead of `settings`. Global settings (provider, models, batch_size, rate limits, etc.) still come from `settings`. --- ## 3. Frontend — "Personnaliser les syntheses" page ### Navigation rename "Sources personnalisees" → "Personnaliser les syntheses" ### Page layout 1. **Theme selector** — dropdown listing all user themes + "Creer un nouveau theme" button 2. **Content settings** — theme name, search topic, categories (add/remove), max age, max items, summary length slider. Moved from Settings page. 3. **Sources** — existing sources list, filtered by selected theme. Add/delete/bulk import scoped to current theme. 4. **Delete theme** — danger button with confirmation. ### Settings page changes Remove the "Contenu" section. Keep: Sources (pipeline tuning), Intelligence Artificielle, Performance, Import/Export. --- ## 4. Frontend — Home page enhancements - **Theme badge** on synthesis cards (below week label). "Theme supprime" for null theme_id. - **Sort toggle**: "Trier par: Date | Theme". Default: Date. Theme sort groups by theme name. - **Generate page**: theme dropdown before "Generate" button. Pre-selects last used theme. --- ## 5. Implementation phases | Phase | Scope | Dependencies | |-------|-------|-------------| | 1 | Data model + backend API (migrations, themes CRUD, pipeline) | None | | 2 | Theme management page (new page, move content settings) | Phase 1 | | 3 | Generation with theme (generate page dropdown) | Phase 1 | | 4 | Home page enhancements (theme badge, sort) | Phase 1 | Each phase produces working software. Phases 2-4 can be done in any order after Phase 1. --- ## Files overview ### Phase 1 (Backend) - **Create:** `backend/migrations/20260326000028_create_themes.sql` - **Create:** `backend/src/db/themes.rs` - **Create:** `backend/src/models/theme.rs` - **Create:** `backend/src/handlers/themes.rs` - **Modify:** `backend/src/db/mod.rs`, `backend/src/models/mod.rs`, `backend/src/handlers/mod.rs` - **Modify:** `backend/src/router.rs` — add theme routes - **Modify:** `backend/src/db/sources.rs` — add `theme_id` filter - **Modify:** `backend/src/db/syntheses.rs` — add `theme_id`, `theme_name` to queries - **Modify:** `backend/src/models/settings.rs` — remove moved fields - **Modify:** `backend/src/db/settings.rs` — remove moved columns from queries - **Modify:** `backend/src/services/synthesis.rs` — load content settings from theme - **Modify:** `backend/src/handlers/generation.rs` — accept `theme_id` ### Phase 2 (Theme page) - **Create:** `frontend/src/pages/ThemeManager.tsx` - **Create:** `frontend/src/api/themes.ts` - **Modify:** `frontend/src/App.tsx` — routes - **Modify:** `frontend/src/components/Navbar.tsx` — rename nav item - **Modify:** `frontend/src/pages/Settings.tsx` — remove Contenu section - **Modify:** `frontend/src/i18n/fr.ts` — labels ### Phase 3 (Generate) - **Modify:** `frontend/src/pages/GenerateSynthesis.tsx` — theme dropdown - **Modify:** `frontend/src/api/syntheses.ts` — pass theme_id ### Phase 4 (Home) - **Modify:** `frontend/src/pages/Home.tsx` — theme badge, sort - **Modify:** `frontend/src/types.ts` — add theme fields to types