# Plan d'alignement Marketing ↔ Code — wordly.art > Analyse effectuée le 2026-08-29, croisée ligne à ligne avec le code backend, la landing et les docs de lancement. > Principe : **le lancement (Product Hunt / Show HN) attire des relecteurs techniques** — chaque promesse non tenue y sera testée publiquement. Ce plan sépare ce qu'il faut corriger **dans les textes** (rapide) de ce qu'il faut corriger **dans le code** (pour tenir les promesses). > > **Statut au 2026-08-29 : vagues A et B appliquées et testées (442 tests backend passent, `tsc --noEmit` landing OK). Restent les items P2 de la vague C.** --- ## 1. Ce qui est déjà conforme ✅ | Affirmation marketing | Vérification code | Statut | |---|---|---| | Prix 0/9/19/49 €, annuel −20 % (7,20/15,20/39,20) | `models/subscription.py:39-155` (86,40/182,40/470,40 €/an) | ✅ exact | | Quotas 2/50/200/1 000 docs, pages 10/50/200/500, fichiers 5/10/25/50 Mo | idem | ✅ exact | | API Business 10 000 appels/mois, 5 sièges | `api_calls_per_month: 10_000`, `team_seats: 5` | ✅ exact | | Crédits 50/5 € · 100/9 € · 250/20 € · 500/35 € · 1 000/60 € (0,06–0,10 €) | `CREDIT_PACKAGES` (`models/subscription.py:316`) | ✅ exact | | Landing : sections pricing/FAQ/preuve/waitlist + Vercel Analytics + waitlist endpoint + compteur | `app/page.tsx`, `components/*`, `routes/waitlist_routes.py` | ✅ en place | | Événements analytics (`translation_started`, `pricing_cta_click`, `waitlist_joined`, `waitlist_error`) | présents dans les 3 composants | ✅ branchés | | Footer sans « SOC 2 » | `app/page.tsx` — mention absente | ✅ corrigé | | Blog Docker : « CORS `*` refuse de démarrer en prod » | `main.py:379-386` (`sys.exit`) | ✅ vrai | | « DeepL moteur des plans payants » | Starter+ : `providers: ["google","deepl",…]` | ✅ exact | | Blog 1 : « à partir de 0,06 €/page » | cohérent avec les crédits (1 page = 1 crédit de base) | ✅ | --- ## 2. Écarts détectés — promesses non tenues par le code ### E1. 🔴 « PDF is on the roadmap » (Show HN + Product Hunt) — FAUX, et ça cache une feature - Show HN : *« (PDF is the obvious next one.) »* · Product Hunt : *« PDF is on the roadmap »*. - **Réel : le PDF est déjà supporté** (`.pdf` dans `SUPPORTED_EXTENSIONS`, mode `layout`/`text_only`, pdf2docx fallback) **et depuis le 2026-08-29 les PDF scannés passent par OCR Mistral** (`services/mistral_ocr.py`) — ce que DeepL et Azure refusent. - **C'est l'inverse : c'est un argument de vente majeur à ajouter.** Telle quelle, la phrase invite les relecteurs HN à trouver une fonctionnalité qui existe déjà dans le dashboard. ### E2. 🔴 « Files auto-deleted after 60 min » (landing, FAQ, Show HN, PH, Reddit, X, blogs 1/3) — inexact - Réel (`config.py`) : uploads **30 min**, résultats **120 min**, TTL générique 60. - Deux options : corriger le texte (« uploads deleted after 30 min, results within 2 h ») **ou** passer `OUTPUT_FILE_TTL_MINUTES` à 60. Recommandation : garder 120 min (l'utilisateur doit pouvoir re-télécharger) et corriger les textes. ### E3. 🔴 « Encrypted at rest » (FAQ §sécurité, X-thread, blog 3 §données) — non implémenté - Aucun chiffrement des fichiers au repos dans le code (uploads/outputs en clair). TLS : dépend du reverse-proxy (vrai en prod nginx+HSTS). - **À retirer des textes** tant que non implémenté (ou implémenter, cf. §3-C5). ### E4. 🟠 « 60+ langues » (landing stats, PH, X-thread) — l'app en expose 35 - Réel : `/api/v1/languages` = **35 langues** ; le sélecteur UI = 35. (Le validateur accepte ~100 codes, mais invisibles pour l'utilisateur.) - Options : (a) corriger le chiffre en « 35 », (b) **exposer les ~60-100 langues déjà validées** côté API/UI — recommandé, c'est un travail faible et les LLM couvrent ces langues. ### E5. 🟠 « 7 moteurs » avec Minimax et DeepSeek cités (FAQ, Show HN) — incohérent avec les plans - Réel (`models/subscription.py`) : Business = `google, google_cloud, deepl, openrouter, openrouter_premium, openai, zai` — **ni Minimax ni DeepSeek direct** (DeepSeek n'est que le modèle IA « essentiel » interne). - Harmoniser : retirer Minimax/DeepSeek des listes, **ou** les ajouter au plan Business (l'endpoint `/providers/available` les expose déjà à l'UI !). ### E6. 🟡 « 100 % formatting preserved » (landing, comparatif, x-thread) — survendu - Cas limites réels : PDF scannés (sortie re-mise en page, pas d'« in place »), placeholders `[translation overflow]` sur débordements, texte dans images non traduit sans l'option vision. - Recommandation : garder la promesse forte mais crédible (« formatting preserved — formulas, merges, styles ») + publier une page « limites connues ». Sur HN, un contre-exemple suffira à casser le « 100 % ». ### E7. 🟠 Blog Docker (auto-hébergement) : 4 erreurs factuelles 1. `GOOGLE_TRANSLATE_API_KEY=...` : **cette variable n'existe pas** — le moteur Google gratuit n'a pas de clé ; le moteur payant = `GOOGLE_CLOUD_API_KEY`. Remplacer par un exempilaire réel du `.env.example`. 2. `pg_dump -U wordly wordly` : les défauts du compose sont **`translate` / `translate_db`**. 3. « L'API sur :8000 » : le compose publie **8001:8000** → c'est `:8001` côté hôte. 4. `git clone https://gitea.parsanet.org/...` : repo privé → rendre public ou générer (`github.com//office-translator`). ### E8. 🟠 Le backend n'applique PAS la grille « moteurs par plan » (fuite de revenus) - Dans `translate_document_v1`, seul `google_cloud` est rétrogradé pour les non-Pro. **Un Free peut envoyer `provider=openai` ou `openrouter_premium`** et consommer les moteurs vendus 49 €/mois. La grille existe pourtant dans `PLANS[plan]["providers"]`. - Idem : **`translate_images` (vision) n'est pas gated**, alors que la FAQ dit « Pro and Business plans ». --- ## 3. Plan d'action ### Vague A — Avant lancement (textes, ~½ journée) — P0 ✅ APPLIQUÉE | # | Action | Fichiers | Statut | |---|---|---|---| | A1 | Remplacer « PDF on the roadmap » par la feature : « PDF supported — incl. scanned PDFs via OCR » | `launch/show-hn.md`, `launch/product-hunt.md` | ✅ | | A2 | Corriger la rétention : « uploads deleted after 30 min, results auto-deleted within 2 h » | landing `social-proof-section.tsx`, `faq-section.tsx`, `show-hn.md`, `product-hunt.md`, `reddit-posts.md`, `x-thread.md`, `blog/1`, `blog/3`, `MARKETING_PLAN.md` | ✅ | | A3 | Supprimer « encrypted at rest » / « at rest » | `faq-section.tsx`, `x-thread.md`, `blog/3` | ✅ | | A4 | Blog Docker : clé `GOOGLE_CLOUD_API_KEY`, `pg_dump` translate/translate_db, port hôte 8001, URL de dépôt générique, + mention MISTRAL_API_KEY | `blog/5-auto-heberger-traduction-docker.md` | ✅ | | A5 | Ajouter PDF (+ OCR scannés) aux formats annoncés : hero, badges `.pdf`, drag & drop + `accept` PDF, FAQ formats | `hero-section.tsx`, `translation-card.tsx`, `faq-section.tsx` | ✅ | ### Vague B — Semaine 1 (code, ~2-3 j) — P1 ✅ APPLIQUÉE | # | Action | Détail | Statut | |---|---|---|---| | B1 | **Gating moteurs par plan** : `translate_document_v1` rejette (403 `PRO_FEATURE_REQUIRED`) tout `provider` hors `PLANS[tier]["providers"]` ; helpers testés (`tests/test_plan_gating.py`) ; `/providers/available` filtré par plan (l'UI ne propose plus un moteur refusé) | ferme la fuite de revenus E8 | ✅ | | B2 | Gater `translate_images` aux plans Pro+ | la FAQ redevient exacte | ✅ | | B3 | Langues : `/api/v1/languages` expose désormais **107 langues nommées** (35 populaires d'abord, puis ordre alphabétique ; `LANGUAGE_NAMES` complété) → la promesse « 60+ » est tenue | E4 résolu par le code | ✅ | | B4 | Moteurs harmonisés : Minimax/DeepSeek retirés des listes marketing (DeepSeek présenté « via OpenRouter ») ; cohérent avec le filtrage du catalogue | résout E5 | ✅ | ### Vague C — Avant le scale — P2 | # | Action | Détail | |---|---|---| | C1 | Remplacer « 100 % » par une promesse démontrable + page « limites connues » (PDF scannés re-mis en page, overflow, images) | E6 | | C2 | Si l'argument « chiffré au repos » est voulu : chiffrer `uploads/`+`outputs/` (clé env `FILES_ENCRYPTION_KEY`, chiffrement AES au write/read) alors seulement réintroduire la mention | E3 | | C3 | Mettre à jour `MARKETING_PLAN.md` : ajouter PDF + OCR scannés aux différenciateurs (vs DeepL/Azure qui refusent les scannés), mentionner webhooks & API keys | valorise l'existant | | C4 | Décider TTL outputs : si la promesse « 60 min » est gardée, passer `OUTPUT_FILE_TTL_MINUTES=60` au lieu de changer 9 textes | alternative à A2 | | C5 | NPS « enquête post-traduction » (source KPI dans MARKETING_PLAN §6) : non implémenté — retirer la ligne ou créer le mini-formulaire post-download | KPIs honnêtes | ### Decision needed (propriétaire) — ✅ TRANCHÉES LE 2026-08-29 - **Rétention** : textes corrigés (A2) — les TTL code restent 30 min / 120 min. - **Langues** : 107 exposées via `/languages` (B3) — la promesse « 60+ » est tenue. - **Minimax/DeepSeek** : retirés du discours commercial (DeepSeek mentionné « via OpenRouter ») ; plans inchangés. --- ## 4. Résumé Le socle commercial du document marketing est **fiable** (prix, quotas, crédits, API, landing, waitlist, analytics : tout correspond au code). Les écarts se concentrent sur **6 chiffres/affirmations répétées** (60 min, 60+ langues, 7 moteurs, 100 %, chiffrement au repos, « PDF à venir ») et **2 trous d'application côté code** (gating moteurs et vision par plan). Les vagues A (textes) et B (code) suffisent pour un lancement PH/HN sans Vulnerabilité factuelle.