You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
584 lines
33 KiB
Markdown
584 lines
33 KiB
Markdown
# UX Analysis: AI Weekly Synth Refactoring
|
|
|
|
**Author**: UX Specialist
|
|
**Date**: 2026-03-21
|
|
**Scope**: Complete UX audit of the current application and analysis of the planned refactoring impact on user experience.
|
|
|
|
---
|
|
|
|
## Open Questions and Clarification Requests
|
|
|
|
Before diving into the analysis, the following ambiguities could lead to UX problems if not resolved early:
|
|
|
|
1. **Existing user migration path**: The current app uses Google SSO exclusively. Requirement #11 introduces email+captcha and magic link auth, but does not mention keeping Google SSO. Will existing Google-authenticated users be able to continue using Google login, or will they be forced to create an email-based account? This is a critical UX decision -- forcing migration risks losing users.
|
|
|
|
2. **Admin role definition**: Requirements #5 and #6 introduce admin modules (API keys, rate limiter). Who is "admin"? Is it a self-hosted single-tenant scenario where the person deploying is the admin? Or is there a multi-tenant SaaS model with a super-admin? The answer fundamentally changes the admin UX.
|
|
|
|
3. **Multi-provider selection granularity**: Requirement #4 says "support multiple LLM providers." Does the admin configure one global provider, or can each user choose their preferred provider? If user-level, do users bring their own API keys, or does the admin provision all keys? This affects both the Settings page and the Admin module.
|
|
|
|
4. **Email sending feature**: The current app sends synthesis by email via the Gmail API (OAuth popup for access token). With Google auth being removed, what replaces this? Backend SMTP? A dedicated email service? Or is this feature dropped?
|
|
|
|
5. **Real-time updates**: The current app uses Firestore `onSnapshot` for real-time data in Home and Sources pages. Will the new backend provide WebSocket/SSE equivalents, or will we switch to polling? This significantly impacts perceived responsiveness.
|
|
|
|
6. **Grounding / Web search capability**: The current pipeline uses Google Gemini's `googleSearch` tool for real-time web grounding. OpenAI and Anthropic do not have equivalent built-in web search. How will web search be handled for non-Google providers? This impacts what the user can expect from the generation.
|
|
|
|
7. **Locale/Language**: The entire UI is in French. Is internationalization planned? This affects how we structure text in the SolidJS rewrite.
|
|
|
|
---
|
|
|
|
## 1. Current UX Inventory
|
|
|
|
### 1.1 Screens and Routes
|
|
|
|
| Route | Screen | Purpose |
|
|
|---|---|---|
|
|
| `/login` | Login | Single-button Google SSO authentication |
|
|
| `/` | Home (Dashboard) | List of all user syntheses as cards, with inline delete (double-click confirm) |
|
|
| `/generate` | Generate Synthesis | One-click synthesis generation with loading/error/success feedback |
|
|
| `/synthesis/:id` | Synthesis Detail | Full reading view of a synthesis, email sending, deletion with modal confirm |
|
|
| `/sources` | Custom Sources | CRUD for custom URLs: single add, CSV import/export, bulk text import |
|
|
| `/settings` | Settings | Generation parameters: theme, age window, categories (dynamic list), AI model, search agent behavior, JSON import/export |
|
|
|
|
### 1.2 Navigation Architecture
|
|
|
|
- **Top navigation bar** (persistent across all authenticated pages):
|
|
- Left: Logo (BrainCircuit icon) + app name link to Home, then two nav links ("Syntheses", "Sources personnalisees")
|
|
- Right: User email display, Settings gear icon link, Logout button
|
|
- **No mobile hamburger menu**: The `sm:` prefix hides the nav links on small screens. The current app has a responsive gap on mobile -- the "Syntheses" and "Sources personnalisees" links disappear on narrow viewports with no alternative navigation.
|
|
- **No breadcrumbs or active route indicator**: Nav links do not highlight the active page.
|
|
|
|
### 1.3 Interaction Patterns Catalog
|
|
|
|
#### Authentication
|
|
- **Login**: Single button "Se connecter avec Google" triggers Firebase `signInWithPopup`. No form fields, no password.
|
|
- **Logout**: Button in navbar triggers `signOut`, returns to `/login` via `ProtectedRoute` redirect.
|
|
- **Session persistence**: Firebase `onAuthStateChanged` auto-restores session on reload.
|
|
|
|
#### Loading States
|
|
- **Full-page spinner**: Used on initial auth check (`ProtectedRoute`) -- centered spinner, full viewport height.
|
|
- **Section spinner**: Used on Home, Sources, Settings, SynthesisDetail -- centered spinner in a 256px-height container.
|
|
- **Inline spinner**: Used on GenerateSynthesis button, Save Settings button, Send Email button, Delete buttons -- small spinner inside the button alongside text.
|
|
- **No skeleton screens**: The app shows spinners, never content placeholders.
|
|
|
|
#### Data Feedback
|
|
- **Success banners**: Green background with left border (GenerateSynthesis), green toast (SynthesisDetail email sent), green inline message (Settings save).
|
|
- **Error banners**: Red background with left border (GenerateSynthesis), red inline message (Sources import, Settings save, SynthesisDetail email error).
|
|
- **Auto-redirect after success**: GenerateSynthesis redirects to the new synthesis detail after 1.5 seconds.
|
|
- **Auto-dismiss**: Delete confirmation on Home cards auto-cancels after 3 seconds if not confirmed.
|
|
|
|
#### Deletion Patterns
|
|
- **Home (card list)**: Two-click inline pattern. First click shows "Confirmer" label + red background on the trash icon. Second click deletes. Auto-resets after 3 seconds.
|
|
- **SynthesisDetail**: Separate delete button in header, opens a persistent confirmation banner with "Annuler" and "Confirmer la suppression" buttons. Does not auto-dismiss.
|
|
- **Sources**: Single-click delete, no confirmation.
|
|
|
|
These three different deletion patterns are inconsistent. The refactoring is an opportunity to standardize.
|
|
|
|
#### Forms
|
|
- **Settings**: All fields are inline-editable. Categories use a dynamic list with add/remove. Save button at bottom. No auto-save. Import/export JSON buttons in header.
|
|
- **Sources**: Add form uses title + URL side-by-side fields with submit button. Bulk import uses a textarea. CSV import uses a hidden file input.
|
|
- **No form validation UI**: Fields use HTML5 `required` attributes but no visible validation messages or field-level error states.
|
|
|
|
#### Content Display
|
|
- **Home cards**: Grid layout (1/2/3 columns responsive), showing week number badge, creation date, preview of first section items (bullet points, line-clamped to 2 lines). Footer with "Lire la synthese" link and delete button.
|
|
- **SynthesisDetail sections**: Vertical list of categorized sections. Each section has a title with bottom border, then cards for each news item (title as external link, summary paragraph).
|
|
- **Legacy data handling**: Both Home and SynthesisDetail gracefully degrade to show old-format fields (`majorAnnouncements`, `financialSector`, etc.) when `sections[]` is absent.
|
|
|
|
### 1.4 Visual Design System
|
|
|
|
- **Color palette**: Indigo as primary (buttons, links, badges, focus rings), gray scale for text/backgrounds/borders, red for destructive actions, green for success states.
|
|
- **Typography**: System defaults via Tailwind (no custom font import). Font sizes range from `text-xs` to `text-3xl`. Bold headings (`font-extrabold`, `font-bold`, `font-semibold`).
|
|
- **Spacing**: Consistent use of Tailwind spacing scale. Max content width varies: `max-w-5xl` (Home), `max-w-4xl` (Sources, SynthesisDetail), `max-w-3xl` (Settings, GenerateSynthesis), `max-w-md` (Login).
|
|
- **Components**: No formal component library. UI is built with raw Tailwind utility classes. Buttons, cards, form inputs are styled inline.
|
|
- **Icons**: `lucide-react` throughout (BrainCircuit, LogOut, Settings, Plus, Trash2, FileText, Loader2, AlertCircle, CheckCircle2, ArrowLeft, ExternalLink, Mail, Send, AlertTriangle, Download, Upload, Link).
|
|
- **Shadows and borders**: Cards use `shadow-sm` with `border-gray-200`, hover state adds `shadow-md` and `border-indigo-300`.
|
|
- **Animations**: Only `animate-spin` on loader spinners. No page transitions, no entrance animations.
|
|
|
|
---
|
|
|
|
## 2. Migration Risks: React to SolidJS
|
|
|
|
### 2.1 Framework-Level Risks
|
|
|
|
| Risk | Severity | Detail |
|
|
|---|---|---|
|
|
| **Reactivity model change** | Medium | React uses re-rendering on state change; SolidJS uses fine-grained reactivity with signals. Components that rely on `useState` + re-render cycles need careful translation to `createSignal`/`createStore`. Incorrect translation can cause stale UI. |
|
|
| **Context API differences** | High | `AuthContext` uses React Context + `useContext`. SolidJS has its own Context API, but reactive propagation works differently. The `useAuth()` hook pattern must be recreated as a SolidJS context with signals. |
|
|
| **Lifecycle hooks** | Medium | `useEffect` with dependency arrays has no direct SolidJS equivalent. SolidJS uses `createEffect` (auto-tracking), `onMount`, and `onCleanup`. The Firestore `onSnapshot` subscriptions in Home, Sources, and SynthesisDetail rely heavily on `useEffect` cleanup -- these must be carefully ported to `onCleanup`. |
|
|
| **Conditional rendering** | Low | React uses ternary/`&&` operators; SolidJS uses `<Show>` and `<For>` components. Straightforward but needs systematic conversion. |
|
|
| **Router** | Medium | Moving from `react-router-dom` v7 to SolidJS Router (`@solidjs/router`). API is similar but different: `useParams`, `useNavigate`, `<A>` instead of `<Link>`, `<Route>` structure. `ProtectedRoute` must be reimplemented as a route guard or layout route. |
|
|
| **Event handling** | Low | Mostly identical (`onClick`, `onChange`, etc.). SolidJS uses `on:click` in some patterns but supports standard JSX event handlers. |
|
|
|
|
### 2.2 UI/UX-Specific Risks
|
|
|
|
| Risk | Impact on UX |
|
|
|---|---|
|
|
| **Loss of real-time updates** | Home and Sources currently use Firestore `onSnapshot` for live updates. If the new backend uses REST API instead, users will not see new/deleted items without refreshing. This is a perceived UX regression. Mitigation: implement WebSocket/SSE for list subscriptions, or at minimum, optimistic UI updates + periodic polling. |
|
|
| **Loading state timing changes** | Currently, Firestore queries resolve in ~100-500ms. REST API calls to a Rust backend may be faster, but they also introduce HTTP overhead and network latency that Firestore's SDK (with local cache) does not have. Loading spinners may appear more frequently or for different durations. |
|
|
| **Icon library change** | `lucide-react` must be replaced by `lucide-solid` or a generic SVG approach. The icon set is identical, but the import pattern changes. Risk of missing icons or inconsistent sizing. |
|
|
| **Tailwind CSS compatibility** | Tailwind is framework-agnostic. The utility classes can be copied verbatim to SolidJS JSX. The main risk is `className` vs `class` -- SolidJS uses `class` (standard HTML attribute). This is a systematic find-and-replace, but if missed, styles silently break with no visual output. |
|
|
| **Date formatting** | `date-fns` is framework-agnostic and can be reused. But `Timestamp.toDate()` from Firestore must be replaced by standard ISO date string parsing from the API. |
|
|
| **Gmail email popup flow** | Currently relies on Firebase `signInWithPopup` to get a Gmail OAuth token. This entire flow disappears. Email sending must be redesigned (see Section 4). |
|
|
|
|
### 2.3 Recommendations for Safe Migration
|
|
|
|
1. **Build a component-by-component mapping** before starting. Every React component should have a SolidJS counterpart spec'd with identical props and behavior.
|
|
2. **Create a SolidJS design system** with extracted, reusable primitives (Button, Card, Spinner, Badge, FormField, ConfirmDialog) to replace the inline Tailwind patterns. This reduces duplication risk.
|
|
3. **Visual regression testing**: Capture screenshots of every screen/state in the current app. Compare against the SolidJS implementation pixel-by-pixel.
|
|
4. **Preserve all Tailwind classes verbatim** (modulo `className` -> `class`).
|
|
5. **Keep `lucide` icons**: Use `lucide-solid` or direct SVG imports to maintain visual consistency.
|
|
|
|
---
|
|
|
|
## 3. New UX Flows: Authentication
|
|
|
|
### 3.1 Current State
|
|
|
|
- Single button: "Se connecter avec Google"
|
|
- No sign-up flow (Google creates the account implicitly)
|
|
- No password management, no email verification
|
|
- Session persisted via Firebase auth token (auto-refresh)
|
|
|
|
### 3.2 Proposed New Flows
|
|
|
|
#### 3.2.1 Sign-Up (Email + Captcha)
|
|
|
|
**Screen**: `/signup`
|
|
|
|
**Flow**:
|
|
1. User lands on Login page, sees "Creer un compte" link below the login form.
|
|
2. Sign-up form with fields:
|
|
- Email address (required, validated format)
|
|
- Display name (optional, for navbar greeting)
|
|
- CAPTCHA widget (e.g., hCaptcha or Cloudflare Turnstile -- avoid Google reCAPTCHA to stay provider-agnostic)
|
|
3. User submits. Backend creates account, sends a magic link to the email.
|
|
4. User sees a confirmation screen: "Un lien de connexion vous a ete envoye a [email]. Verifiez votre boite de reception."
|
|
5. User clicks the magic link in their email, which authenticates them and redirects to `/`.
|
|
|
|
**UX considerations**:
|
|
- No password field. The magic link serves as both email verification and initial authentication. This is simpler, more secure, and avoids the need for password complexity rules, forgot-password flows, and password storage.
|
|
- CAPTCHA should be invisible or minimally intrusive (Turnstile "managed" mode). A full visual puzzle challenge degrades conversion.
|
|
- The sign-up confirmation screen must handle edge cases: email not received (resend button with cooldown), email in spam, typo in email (back button to re-enter).
|
|
|
|
#### 3.2.2 Login (Magic Link / Passwordless)
|
|
|
|
**Screen**: `/login`
|
|
|
|
**Flow**:
|
|
1. User enters their email address.
|
|
2. User completes CAPTCHA (if not previously solved in session).
|
|
3. Backend sends a magic link to the email.
|
|
4. User sees: "Un lien de connexion vous a ete envoye a [email]."
|
|
5. User clicks the link, which sets a session cookie and redirects to `/`.
|
|
|
|
**UX considerations**:
|
|
- The magic link should expire (e.g., 15 minutes) and be single-use.
|
|
- If the user tries to log in with an unregistered email, the system should respond with the same message ("link sent") to prevent email enumeration attacks. Alternatively, offer to create the account.
|
|
- Provide a "Renvoyer le lien" button with a cooldown timer (e.g., 60 seconds) on the confirmation screen.
|
|
- Consider deep-link support: if the user clicks the magic link on a different device/browser, the new session should be created there instead.
|
|
|
|
#### 3.2.3 Session Management
|
|
|
|
**Current**: Firebase manages JWT tokens client-side, auto-refreshes.
|
|
**Proposed**: Session-based auth with secure cookies (HttpOnly, Secure, SameSite=Strict).
|
|
|
|
**UX implications**:
|
|
- Session expiry must be handled gracefully. If a session expires while the user is on a page, the next API call will return 401. The frontend must catch this and redirect to `/login` with a message: "Votre session a expire. Veuillez vous reconnecter."
|
|
- No more `onAuthStateChanged` listener. The SolidJS auth context must check session validity on app load (e.g., `GET /api/auth/me` endpoint).
|
|
- Consider a session duration of at least 7 days (with sliding window) to avoid forcing weekly login on a weekly-use app.
|
|
- Logout must call a backend endpoint to invalidate the server-side session, not just clear client state.
|
|
|
|
#### 3.2.4 Login Page Redesign
|
|
|
|
The new login page should accommodate both login and sign-up while preserving the visual identity:
|
|
|
|
```
|
|
+----------------------------------------------+
|
|
| [BrainCircuit icon] |
|
|
| AI Weekly Synth |
|
|
| Votre synthese hebdomadaire des actualites |
|
|
| |
|
|
| [Email address field ] |
|
|
| [ Turnstile CAPTCHA widget ] |
|
|
| [ Recevoir un lien de connexion ] |
|
|
| |
|
|
| Pas encore de compte ? Creer un compte |
|
|
+----------------------------------------------+
|
|
```
|
|
|
|
For sign-up, swap to:
|
|
```
|
|
| [Email address field ] |
|
|
| [Display name (optionnel) ] |
|
|
| [ Turnstile CAPTCHA widget ] |
|
|
| [ Creer mon compte ] |
|
|
| |
|
|
| Deja un compte ? Se connecter |
|
|
```
|
|
|
|
### 3.3 Migration Path for Existing Google SSO Users
|
|
|
|
This is the most sensitive UX challenge. Options:
|
|
|
|
**Option A (Recommended): Dual auth during transition period**
|
|
- Keep Google SSO as an option alongside the new email-based auth for 3-6 months.
|
|
- When a Google-authenticated user logs in, prompt them to add an email address to their account: "Pour assurer la continuite de votre compte, veuillez associer une adresse email."
|
|
- Once the email is associated, both login methods work.
|
|
- After the transition period, remove Google SSO.
|
|
- Pro: Zero friction for existing users. Con: Maintains two auth systems temporarily.
|
|
|
|
**Option B: Forced migration on first visit**
|
|
- On first visit to the new app, the old Google session is invalid.
|
|
- Show a migration screen: "Nous avons mis a jour notre systeme d'authentification. Entrez l'adresse email associee a votre compte Google pour recevoir un lien de connexion."
|
|
- Backend matches the email from the old Google auth record to migrate the account.
|
|
- Pro: Clean cut. Con: Users with different Google/personal emails may struggle.
|
|
|
|
**Option C: Pre-migration email campaign**
|
|
- Before deploying the new auth system, send an email to all existing users explaining the change and providing a pre-migration link.
|
|
- Pro: Users are prepared. Con: Some users will ignore the email and be confused.
|
|
|
|
**Recommendation**: Option A provides the smoothest UX. Existing users notice no disruption while new users get the new flow.
|
|
|
|
---
|
|
|
|
## 4. Admin Module UX
|
|
|
|
### 4.1 Access Model
|
|
|
|
**Recommendation**: The first user to register becomes the admin (self-hosted model). Alternatively, admin is designated via environment variable or CLI command at deployment time. There should be no in-app admin registration -- it is a deployment-time decision.
|
|
|
|
Admin pages should be:
|
|
- Hidden from navigation for non-admin users (not just disabled -- completely absent from the DOM).
|
|
- Protected by both frontend route guards and backend authorization.
|
|
- Accessible via a gear/shield icon in the navbar, only visible to admins.
|
|
|
|
### 4.2 Admin Navigation
|
|
|
|
Add an admin section to the navbar (visible only to admin users):
|
|
|
|
```
|
|
[Logo] AI Weekly Synth | Syntheses | Sources | [Admin dropdown: Configuration LLM | Limites d'usage] | [user@email] [Settings] [Logout]
|
|
```
|
|
|
|
Or a dedicated `/admin` layout with sidebar:
|
|
```
|
|
/admin/llm-providers -- API key management
|
|
/admin/rate-limits -- Rate limiter configuration
|
|
/admin/users -- (future) User management
|
|
```
|
|
|
|
**Recommendation**: Use a separate `/admin` route prefix with its own layout. Keeps admin concerns cleanly separated and makes authorization simpler.
|
|
|
|
### 4.3 API Key Configuration Page (`/admin/llm-providers`)
|
|
|
|
**Layout**:
|
|
```
|
|
+------------------------------------------------------+
|
|
| Configuration des fournisseurs LLM |
|
|
| |
|
|
| [Google Gemini] [OpenAI] [Anthropic] |
|
|
| (card/tab per provider) |
|
|
| |
|
|
| --- Google Gemini --- |
|
|
| Cle API: [********************] [Show/Hide] [Test] |
|
|
| Statut: Connecte (dernier test: il y a 2 min) |
|
|
| Modeles disponibles: |
|
|
| [x] gemini-3.1-pro-preview |
|
|
| [x] gemini-3-flash-preview |
|
|
| [ ] gemini-3.1-flash-lite-preview |
|
|
| Modele par defaut: [dropdown] |
|
|
| |
|
|
| [Enregistrer] |
|
|
+------------------------------------------------------+
|
|
```
|
|
|
|
**Key UX decisions**:
|
|
- API keys must be masked by default (show dots), with a toggle to reveal.
|
|
- A "Test connection" button per provider validates the key and lists available models.
|
|
- Clear status indicators: green dot = connected/valid, red dot = invalid/expired, gray dot = not configured.
|
|
- The list of enabled models feeds the dropdown in user Settings.
|
|
|
|
### 4.4 Rate Limiter Configuration Page (`/admin/rate-limits`)
|
|
|
|
**Layout**:
|
|
```
|
|
+------------------------------------------------------+
|
|
| Configuration des limites d'usage |
|
|
| |
|
|
| --- Limites globales --- |
|
|
| Requetes max par minute (tous utilisateurs): [30] |
|
|
| Requetes max par utilisateur par jour: [10] |
|
|
| |
|
|
| --- Par fournisseur --- |
|
|
| Google Gemini: |
|
|
| Requetes max / minute: [29] |
|
|
| OpenAI: |
|
|
| Requetes max / minute: [60] |
|
|
| Anthropic: |
|
|
| Requetes max / minute: [50] |
|
|
| |
|
|
| [Enregistrer] |
|
|
+------------------------------------------------------+
|
|
```
|
|
|
|
**Key UX decisions**:
|
|
- Show current usage stats if available (requests today, current rate).
|
|
- Explain what happens when a limit is reached: "L'utilisateur verra un message d'erreur lui demandant de reessayer plus tard."
|
|
- Provide sensible defaults that match free-tier quotas of each provider.
|
|
|
|
---
|
|
|
|
## 5. Multi-Provider UX: Impact on Settings Page
|
|
|
|
### 5.1 Current Settings Page Structure
|
|
|
|
The Settings page currently has one "Modele d'IA" dropdown with 4 Gemini-only options, hardcoded in the JSX.
|
|
|
|
### 5.2 Proposed Redesign
|
|
|
|
Replace the single dropdown with a two-level selection:
|
|
|
|
```
|
|
Fournisseur d'IA:
|
|
[Google Gemini v] (dropdown, only shows providers configured by admin)
|
|
|
|
Modele:
|
|
[gemini-3.1-pro-preview (conseille) v] (dropdown, populated dynamically based on selected provider)
|
|
```
|
|
|
|
**UX considerations**:
|
|
- If the admin has only configured one provider, hide the provider dropdown entirely and show just the model dropdown. This avoids unnecessary complexity for simple setups.
|
|
- If a previously selected provider is removed by the admin, show a warning on the Settings page: "Le fournisseur que vous utilisiez n'est plus disponible. Veuillez en selectionner un autre."
|
|
- Display a brief description of each model (speed vs. quality tradeoff) to help users choose.
|
|
- The "Comportement de l'agent de recherche" textarea should include a note about web search availability: "Note : la recherche web en temps reel est disponible uniquement avec Google Gemini."
|
|
|
|
### 5.3 Impact on GenerateSynthesis Page
|
|
|
|
The generation confirmation text should show the selected provider and model:
|
|
> "Cette action va lancer l'analyse des actualites des **7 derniers jours** sur le theme **"Intelligence Artificielle"** via **Google Gemini (gemini-3.1-pro-preview)**."
|
|
|
|
If the selected provider does not support web search grounding, add a warning:
|
|
> "Note : Le fournisseur selectionne ne dispose pas de la recherche web integree. Les resultats seront bases sur les connaissances du modele uniquement."
|
|
|
|
---
|
|
|
|
## 6. Loading States and Feedback with Backend AI Calls
|
|
|
|
### 6.1 Current Behavior
|
|
|
|
- GenerateSynthesis shows a single spinner with "Generation en cours..." for the entire process.
|
|
- The process runs in the browser (Gemini API calls + CORS proxy scraping), typically taking 30-90 seconds.
|
|
- No progress indication, no intermediate feedback.
|
|
- If the user navigates away, the generation is lost.
|
|
|
|
### 6.2 New Backend Processing: UX Implications
|
|
|
|
Moving AI calls to the backend changes the timing and feedback model:
|
|
|
|
**Advantages**:
|
|
- The generation survives page navigation (backend keeps processing).
|
|
- No CORS proxy issues (backend fetches URLs directly).
|
|
- API keys are secure.
|
|
|
|
**New challenges**:
|
|
- Longer perceived wait if no intermediate feedback.
|
|
- HTTP request timeout risk (if generation takes > 60s, reverse proxies may cut the connection).
|
|
- User may think the app is frozen.
|
|
|
|
### 6.3 Recommended Approach: Server-Sent Events (SSE) for Progress
|
|
|
|
**Flow**:
|
|
1. User clicks "Lancer la generation."
|
|
2. Frontend sends `POST /api/syntheses/generate` which returns immediately with a `task_id`.
|
|
3. Frontend opens an SSE connection: `GET /api/syntheses/generate/{task_id}/progress`.
|
|
4. Backend sends progress events:
|
|
```
|
|
event: progress
|
|
data: {"step": "search", "message": "Recherche d'actualites en cours...", "percent": 10}
|
|
|
|
event: progress
|
|
data: {"step": "scraping", "message": "Verification des sources (3/12)...", "percent": 40}
|
|
|
|
event: progress
|
|
data: {"step": "rewrite", "message": "Redaction des resumes...", "percent": 75}
|
|
|
|
event: progress
|
|
data: {"step": "saving", "message": "Sauvegarde...", "percent": 95}
|
|
|
|
event: complete
|
|
data: {"synthesis_id": "abc123"}
|
|
|
|
event: error
|
|
data: {"message": "Quota depasse. Reessayez plus tard."}
|
|
```
|
|
5. Frontend displays a progress bar with step descriptions.
|
|
|
|
**Proposed UI for generation page**:
|
|
```
|
|
+----------------------------------------------+
|
|
| Generer la Synthese Hebdomadaire |
|
|
| |
|
|
| [========================------] 75% |
|
|
| Redaction des resumes... |
|
|
| |
|
|
| Etapes: |
|
|
| [done] Recherche d'actualites |
|
|
| [done] Verification des 12 sources |
|
|
| [>> ] Redaction des resumes |
|
|
| [ ] Sauvegarde |
|
|
| |
|
|
| Note : Vous pouvez quitter cette page. |
|
|
| La generation continuera en arriere-plan. |
|
|
+----------------------------------------------+
|
|
```
|
|
|
|
**If the user navigates away and comes back**:
|
|
- The Home page should show a banner: "Une generation est en cours... [Voir la progression]"
|
|
- Or the new synthesis appears in the list with a "En cours..." badge that updates in real-time.
|
|
|
|
### 6.4 Fallback: Polling
|
|
|
|
If SSE is not feasible in the first iteration:
|
|
1. `POST /api/syntheses/generate` returns `{ "task_id": "abc123" }`.
|
|
2. Frontend polls `GET /api/syntheses/generate/{task_id}/status` every 3 seconds.
|
|
3. UI shows an indeterminate spinner with rotating messages:
|
|
- "Recherche en cours..."
|
|
- "Analyse des sources..."
|
|
- "Redaction des resumes..."
|
|
4. On completion, auto-redirect to synthesis detail page (preserving current behavior).
|
|
|
|
### 6.5 Streaming the Synthesis Content
|
|
|
|
A more ambitious approach: stream the synthesis content as it is generated (section by section). The user sees sections appear progressively, similar to a chat interface. This provides the richest feedback but requires significant backend work (streaming JSON fragments or markdown).
|
|
|
|
**Recommendation for MVP**: Implement the SSE progress approach. Reserve streaming content for a later iteration.
|
|
|
|
---
|
|
|
|
## 7. Email Feature Redesign
|
|
|
|
### 7.1 Current Implementation
|
|
|
|
- Hardcoded default email (`olivier.abrivard@desjardins.com` -- this should be removed/replaced).
|
|
- Uses Gmail API directly from the frontend via OAuth popup.
|
|
- Tied to Google authentication.
|
|
|
|
### 7.2 Proposed Replacement
|
|
|
|
**Backend SMTP approach**:
|
|
- Move email sending to `POST /api/syntheses/{id}/send-email` on the backend.
|
|
- Admin configures SMTP settings in the admin panel (or via environment variables): SMTP host, port, username, password, sender address.
|
|
- User enters recipient email on the SynthesisDetail page (same UI as today, minus the Gmail-specific parts).
|
|
- Default recipient should be the user's own email address (from their account).
|
|
|
|
**UX changes**:
|
|
- Remove the Gmail OAuth popup entirely.
|
|
- The "Envoyer par email" button triggers a backend call.
|
|
- Add a small loading spinner on the button (already exists in current UI).
|
|
- Success/error feedback remains the same.
|
|
- Consider adding a "S'envoyer a soi-meme" quick button that pre-fills with the user's account email.
|
|
|
|
### 7.3 Admin SMTP Configuration Page
|
|
|
|
If email functionality requires admin SMTP setup, add a section to the admin area:
|
|
```
|
|
--- Configuration email ---
|
|
Serveur SMTP: [smtp.example.com]
|
|
Port: [587]
|
|
Utilisateur: [user@example.com]
|
|
Mot de passe: [********]
|
|
Adresse d'expedition: [noreply@example.com]
|
|
Chiffrement: [STARTTLS v]
|
|
[Tester l'envoi] [Enregistrer]
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Additional UX Improvements to Include in the Refactoring
|
|
|
|
The refactoring is an opportunity to fix existing UX issues. The following are not new requirements but improvements that should be made while the UI is being rewritten.
|
|
|
|
### 8.1 Mobile Navigation
|
|
|
|
**Problem**: The current nav links ("Syntheses", "Sources personnalisees") are hidden on mobile (`hidden sm:ml-6 sm:flex`) with no alternative.
|
|
**Fix**: Add a hamburger menu for mobile viewports, or a bottom navigation bar.
|
|
|
|
### 8.2 Consistent Deletion Pattern
|
|
|
|
**Problem**: Three different deletion patterns across the app (inline double-click, modal confirm, single-click no confirm).
|
|
**Fix**: Standardize on a confirmation dialog (modal or inline banner) for all destructive actions.
|
|
|
|
### 8.3 Active Route Indicator
|
|
|
|
**Problem**: Nav links do not indicate which page is active.
|
|
**Fix**: Add `border-indigo-500 text-gray-900` classes to the active link (the border-b-2 is already in the HTML, just always set to `border-transparent`).
|
|
|
|
### 8.4 Empty States
|
|
|
|
**Problem**: Sources and Home have empty states, but they could be richer.
|
|
**Fix**: Add contextual onboarding hints. E.g., on first visit to Sources: "L'ajout de sources permet a l'IA de consulter vos sites preferes en priorite."
|
|
|
|
### 8.5 Error Boundary
|
|
|
|
**Problem**: No error boundary exists. A crash in any component brings down the entire app.
|
|
**Fix**: Add a top-level error boundary in SolidJS (`ErrorBoundary` component) with a user-friendly fallback page.
|
|
|
|
### 8.6 Form Validation
|
|
|
|
**Problem**: No visible validation feedback on form fields.
|
|
**Fix**: Add field-level error messages (red text below fields) for invalid inputs (e.g., malformed URL, empty required fields, invalid email format on login).
|
|
|
|
### 8.7 Accessibility
|
|
|
|
**Problem**: Screen reader labels are minimal (`sr-only` labels on some inputs). No `aria-live` regions for dynamic content updates. No keyboard navigation testing.
|
|
**Fix**: Audit all interactive elements for ARIA attributes, ensure focus management on route changes, add `aria-live="polite"` on success/error messages.
|
|
|
|
### 8.8 Hardcoded Email
|
|
|
|
**Problem**: `SynthesisDetail.tsx` line 41 hardcodes `olivier.abrivard@desjardins.com` as the default email.
|
|
**Fix**: Default to the authenticated user's email address, or empty.
|
|
|
|
---
|
|
|
|
## 9. Summary of UX Impact by Requirement
|
|
|
|
| Req # | Requirement | UX Impact | Risk Level |
|
|
|---|---|---|---|
|
|
| 1 | Rust + SQLite backend | Invisible to user if API contracts match | Low |
|
|
| 2 | Convert Firestore rules | Invisible to user | None |
|
|
| 3 | Move AI calls to backend | Major: loading/feedback redesign, generation survives navigation | High |
|
|
| 4 | Multiple LLM providers | Medium: Settings page redesign, provider-dependent feature availability | Medium |
|
|
| 5 | Admin API key config | New screens for admin only | Medium |
|
|
| 6 | Admin rate limiter config | New screens for admin only | Low |
|
|
| 7 | SolidJS frontend | Full rewrite risk, every screen must be verified | High |
|
|
| 8 | Remove legacy data/code | Positive: cleaner data model, simpler rendering | Low |
|
|
| 9 | Improve CORS proxy | Invisible to user (backend handles it now) | None |
|
|
| 10 | Docker deployment | Invisible to user | None |
|
|
| 11 | New auth system | Major: new login/signup flows, migration of existing users | Critical |
|
|
|
|
### Priority Order for UX Work
|
|
|
|
1. **Auth system design** (Req #11) -- must be finalized first as it gates all other flows.
|
|
2. **SolidJS component mapping** (Req #7) -- defines the implementation structure for everything.
|
|
3. **Generation feedback/progress** (Req #3) -- highest-impact user-facing change.
|
|
4. **Multi-provider Settings** (Req #4) -- affects core user workflow.
|
|
5. **Admin module design** (Req #5, #6) -- separate from main user flows, can be parallelized.
|
|
6. **Legacy cleanup** (Req #8) -- simplifies rendering code during rewrite.
|
|
|
|
---
|
|
|
|
## 10. File Reference
|
|
|
|
All analysis is based on the following source files:
|
|
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/CLAUDE.md` -- project documentation
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/App.tsx` -- router, layout, login, protected routes
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/pages/Home.tsx` -- dashboard with synthesis list
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/pages/GenerateSynthesis.tsx` -- generation trigger page
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/pages/SynthesisDetail.tsx` -- synthesis reading view + email
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/pages/Sources.tsx` -- custom sources CRUD
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/pages/Settings.tsx` -- user settings
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/components/AuthContext.tsx` -- auth context provider
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/types.ts` -- TypeScript interfaces and defaults
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/services/geminiService.ts` -- AI generation pipeline
|
|
- `/Users/oabrivard/Projects/rust/ai_synth/src/firebase.ts` -- Firebase init, auth helpers, error handling
|