---
target: frontend/src (UI complète Wordly.art)
total_score: 24
max_score: 40
na_heuristics: 
p0_count: 0
p1_count: 3
timestamp: 2026-08-30T19-50-34Z
slug: frontend-src
---
# Critique de design — Wordly.art (`frontend/src`) — re-run post-correctif

Method: dual-agent (A: agent_8b2492dd-bd0c-48a2-9293-d6c7960dc418 · B: agent_d8eeec19-1e9d-4df5-84a2-7eb2daf6beb0)

## Design Health Score

| # | Heuristique | Score | Problème clé | Δ |
|---|-------------|-------|--------------|---|
| 1 | Visibilité du statut | 3 | Progression aria-live, temps restant API affiché, skeletons ; mais « Tout approuver » boucle sans progression (`reviews/[jobId]/page.tsx:138-148`) et la sauvegarde des consignes simule un délai de 300 ms (`glossaries/page.tsx:64`). | +1 |
| 2 | Correspondance avec le réel | 2 | Jargon non défini : bouton nu « XLIFF » (`reviews/[jobId]/page.tsx:253`), « Phase 2 : Reconstruction contextuelle » (`fr/translate.json:70`) ; membre d'équipe affiché en `user_id.slice(0,8)…` (`teams/page.tsx:197`) ; « Standard » codé en dur EN (`ProviderSelector.tsx:161`). | = |
| 3 | Contrôle et liberté | 3 | Reprise du job après refresh (`useTranslationSubmit.ts:257-278`), sortie honnête « la traduction continue en arrière-plan » ; mais aucune annulation réelle d'un job, et le consentement cookies n'est plus rouvrable (`cookie-consent.tsx:14-26`). | +1 |
| 4 | Cohérence et standards | 2 | Trois systèmes visuels (éditorial serif / font-black pricing-settings / shadcn brut reviews-teams) ; `GlossaryCard.tsx` mort, jamais importé ; aria-label « Close notification » non traduit (`notification.tsx:184`). | +1 |
| 5 | Prévention des erreurs | 3 | Validation extension+taille, avertissements mismatch glossaire avant soumission, submit désactivé avec raison ; mais rien n'empêche source = cible (`useTranslationConfig.ts:233-237`). | +1 |
| 6 | Reconnaissance plutôt que rappel | 3 | Traductions récentes accessibles, récap config pendant l'attente ; mais actions de ligne icône-seule avec `title` seulement (`reviews/[jobId]/page.tsx:364-395`) et onglet « Consignes de contexte » caché sous Glossaires. | = |
| 7 | Flexibilité et efficacité | 1 | Aucun raccourci clavier global ; upload strictement mono-fichier (pas de `multiple`) ; historique plafonné à 8 jobs locaux, aucune page historique serveur ; pas de navigation fléchée dans le combobox langues. | = |
| 8 | Esthétique et minimalisme | 2 | Pricing = 5 plans + comparatif 10 lignes + 4 packs crédits + 4 trust + 2 modèles IA + 7 FAQ ; hiérarchie inversée sur translate — titre décoratif 5xl plus fort que le CTA 12px (`translate/page.tsx:230` vs `:351`). | = |
| 9 | Récupération d'erreurs | 3 | Humanisation en 9 familles, retry avec fichier conservé, cap polling réseau clair ; mais teams/reviews affichent `err.message` brut (`teams/page.tsx:102-105`). | = |
| 10 | Aide et documentation | 2 | Aides contextuelles réelles (glossaire, providers) mais zéro centre d'aide, zéro onboarding première connexion. | = |
| **Total** | | **24/40** | **Acceptable — en limite haute, la bande « Good » (28+) est atteignable** | **+4** |

## Verdict de spécificité design

**LLM assessment** : la landing est « presque signée » — le langage éditorial (Playfair/crème/encre/or) est tenu jusqu'au dashboard, et `SplitTitle` (base + accent italique, `translate/page.tsx:62-64`) est une vraie signature. Le dashboard translate est la meilleure surface : pipeline Upload→Search→Languages→Wrench→Check, glossaire avec paires de langues et ajout inline, providers thémés — rien de réutilisable tel quel par un autre produit. Restent trois failles d'identité : le hero landing (photo Unsplash + fausses cartes UI ne correspondant à aucun écran réel, `landing-page.tsx:139-167`), la page pricing qui parle une typographie opposée (`font-black uppercase tracking-tighter`, `pricing/page.tsx:504`), et reviews/teams jamais passés au design (shadcn brut). Occasion manquée majeure : aucun avant/après de document — LE visuel de la promesse « keep the format ».

**Deterministic scan** : 3 findings (4 avant le correctif). Le `side-tab` du profil est corrigé. Restent 2 `overused-font` Inter (`globals.css:141,147`) — choix assumé « outil sobre » de l'utilisateur, documenté — et 1 `border-accent-on-rounded` (`globals.css:215`) : **faux positif manifeste** (spinner canonique).

**Overlays navigateur** : indisponibles — « Browser is not available in subagent » (identique au run précédent, tentative réelle faite). Fallback : scan CLI.

## Impression générale

Le cœur produit est devenu solide : machine à états propre, reprise après refresh — « peu de SaaS gèrent le rafraîchissement en cours de traitement aussi proprement » —, erreurs humanisées, prévention au point de décision. La confiance n'est plus sabordée. Le plafond suivant se joue sur trois fronts : la conformité AA des micro-labels, l'unification des trois systèmes visuels, et les accélérateurs (batch, raccourcis, historique serveur) qui font la différence pour les utilisateurs intensifs.

## Ce qui fonctionne

1. **La machine à états + persistance du job** : cinq états nets, en-tête réécrit par état, progression réelle backend, localStorage avec TTL 24 h et reprise automatique (`useTranslationSubmit.ts:253-278`).
2. **L'identité éditoriale tenue de la landing au dashboard** : crème/encre/or + serif d'accent + pills, dark mode cohérent, `prefers-reduced-motion`/`prefers-contrast` gérés.
3. **La prévention et la récupération au point de décision** : mapping 9 familles d'erreurs + avertissements mismatch glossaire avant soumission (`GlossarySelector.tsx:340-357`).

## Problèmes prioritaires

1. **[P1] Contraste des micro-labels : illisibles et non-conformes AA.** Textes fonctionnels 9-11px en /20-/40 : nav sidebar `/40` (`DashboardSidebar.tsx:45-48`), stats pricing `text-[9px]/40` (`pricing/page.tsx:636`), « .DOCX » `/20` (`landing-page.tsx:307`). /40 sur crème ≈ 2.5:1. → Fix : plancher 11px, opacité ≥65 %, /20-/30 réservé à la décoration. **→ `$impeccable audit` + `$impeccable harden`**
2. **[P1] Trois systèmes de design qui ne se parlent pas.** Pricing/settings/services en `font-black uppercase` vs translate/glossaries en serif éditorial vs reviews/teams en shadcn brut ; `GlossaryCard.tsx` mort et divergent. → Fix : composant `PageHeader` unique (pill + titre base/accent) imposé partout ; supprimer GlossaryCard. **→ `$impeccable layout` + `$impeccable typeset`**
3. **[P1] UI non traduite dans un produit de traduction.** Chips de suggestions des consignes codées en dur FR (`glossaries/page.tsx:22-29`), « Standard » EN (`ProviderSelector.tsx:161`), « Close notification » (`notification.tsx:184`), strings FR sans accents dans `model-combobox.tsx:32,114,135`, littéraux `|| 'français'` résiduels. → Fix : extraire en clés, bannir le littéral JSX. **→ `$impeccable harden`**
4. **[P2] Actions icône-seule et identité technique exposée.** Éditer/approuver/reset en icônes 12px avec `title` seulement ; membres affichés `user_id.slice(0,8)…`. → Fix : boutons textuels compacts ou icône + libellé visible ; afficher e-mail/nom via l'API. **→ `$impeccable clarify`**
5. **[P2] Aucun accélérateur pour les utilisateurs intensifs.** Pas de Ctrl+Entrée, upload mono-fichier, historique 8 items locaux sans page serveur, pas de fléchées dans le combobox langues (40 options = 40 Tab). → Fix : raccourci, `multiple` + file d'attente, page Historique API, roving tabindex. **→ `$impeccable shape`**

## Red flags personas

**Alex (expert pressé)** : la config par défaut rend le flux rapide — mais 10 fichiers = 10 parcours complets (pas de `multiple`) ; « + Nouvelle traduction » réinitialise tout sans « re-traduire avec la même config » ; historique limité à 8 items locaux ; « Tout approuver » sans confirmation ni undo sur 400 segments.

**Sam (accessibilité)** : les fondations sont désormais réelles — `:focus-visible` global, dropzone focusable avec rôle + Entrée/Espace, progression aria-live, `role="switch"` : du sérieux. Échecs restants : contrastes /40-/20 massifs, dropdowns glossaire sans Échap ni gestion de focus out (`GlossarySelector.tsx:121-129`), combobox langues sans navigation fléchée, « edited » signifié par la couleur seule dans la cellule (sauvé par le badge).

**Jordan (premier usage)** : dropzone auto-explicative, chips rassurantes. Mais « XLIFF »/« Reconstruire et télécharger » sans explication, « Phase 2 : Reconstruction contextuelle » jargon interne, onglet « Consignes de contexte » introuvable par déduction, aucun onboarding première connexion, erreur 60 Mo sans limite affichée ni conseil.

## Observations mineures

Cookie consent non rouvrable + emoji 🍪 + chevauchement possible avec la barre mobile · hero Unsplash → vrai screenshot produit · mailto: brut pour Enterprise (sortie d'app) · switch « Traduire les images » fantôme pour les free · timer `formatElapsed` remis à 0 sur certains changements de statut · clés mortes fr/translate.json (« 100% SÉCURISÉ », « Qualité Maître », cancelProcess) · `model-combobox.tsx` référence des tokens inexistants (`bg-surface`, `border-border-subtle`) · nav dupliquée sidebar/header mobile · auto-checkout silencieux par paramètre d'URL `?plan=` sans re-confirmation (`pricing/page.tsx:339-349`).

## Questions à considérer

1. Pourquoi montrer six groupes de configuration à un free dont la moitié est verrouillée ? Que perdriez-vous à une page translate free de trois contrôles exactement ?
2. Où est le avant/après ? La promesse unique est « keep the format » et nulle part l'UI ne montre un document source à côté de sa traduction — surtout en RTL.
3. Pourquoi le paiement, moment de plus haute anxiété, est-il le seul sans écran de confirmation — et combien d'auto-checkouts silencieux par URL coûtent en litiges ?
