Défi Claude Code n°1 : Dicode
Une app iOS et Android, neuf dictionnaires et un site de 94 000 pages, sans écrire une ligne de code
Cyril Feraudet · 19 octobre 2026
À 15 ans, passionné d’électronique, d’informatique et de radiocommunications, je passe l’examen de radioamateur. Le ministère des Postes et Télécommunications me délivre l’indicatif radio FA1TMV, puis F1TMV à 16 ans. Ce milieu me fait rencontrer des passionnés bien plus âgés que moi, qui deviendront quelques années plus tard mes collègues de travail.
Leur vocabulaire n’est pas celui d’un ado de 16 ans. Beaucoup de mots courants chez les adultes me sont alors inconnus. Par frustration, je décide de lire le dictionnaire en entier.
On me prend pour un dingue quand je raconte ça. En réalité, ça va vite : on saute les mots qu’on connaît déjà, et ceux dont le début de la définition montre qu’ils n’ont pas d’intérêt immédiat. Pour être honnête, du fait de ce filtrage, je ne l’ai pas réellement lu en entier.
Aujourd’hui, mes enfants ont 15 ans et bientôt 17. Début janvier, je leur ai suggéré de faire la même chose. Autant pisser dans un violon, vous imaginez.
D’où l’idée (parce que sans idée, pas de projet) : reprendre le scroll infini des réseaux sociaux pour en faire un dictionnaire. Un mot par écran, du spaced repetition (algorithme SM-2) qui fait revenir chaque mot au bon moment, et des quiz. C’est Dicode.
Le défi, car c’est bien de cela qu’il s’agit : ne pas écrire une seule ligne de code. Tout a été écrit par Claude Code, uniquement en lui dictant mes specs et en travaillant sur son harness, plus particulièrement ses tools et ses MCP. Moi, je relis, je teste sur mon smartphone et je tranche.
Cet article raconte les huit mois et demi qui séparent le premier commit, le 1er février 2026, de la version 1.30.4 publiée sur les stores le 18 octobre. Avec ce qui a marché, ce qui a foiré, et ce que Claude ne fait pas.

Ce que fait Dicode
Dicode est une app iOS et Android de vocabulaire. On fait défiler les mots comme un feed de réseau social. Pour chaque mot, on choisit son niveau de lecture : la même entrée « éphémère » se lit « comme un papillon qui vit juste un jour » au niveau CP, et devient une « propriété ontologique de ce qui est constitutivement voué à la finitude temporelle » au niveau doctorat. Un swipe à droite range le mot dans « trop facile », un swipe à gauche le fait revenir en révision.
Elle contient neuf dictionnaires, tous hors ligne, embarqués dans l’app :
| Dictionnaire | Contenu |
|---|---|
| Français général | 476 315 mots, 7 niveaux de définition du CP au doctorat |
| Droit | 14 228 termes |
| Latin | 11 647 définitions, 249 978 formes fléchies |
| Grec ancien | 10 229 définitions |
| Intelligence artificielle | 2 704 termes |
| Géographie | 2 495 définitions, avec drapeaux |
| Histoire | 2 417 définitions, quatre frises chronologiques |
| Orthographe | 1 934 pièges |
| Philosophie | 532 définitions |
Le tout fait 240 592 questions de quiz. À côté, le site https://dicode.fr publie 94 069 définitions, et un widget permet à n’importe quel site d’afficher la définition d’un mot quand on clique dessus.

1. Tout commence par un CLAUDE.md
Claude Code lit au démarrage un fichier CLAUDE.md à la racine du repo. C’est là qu’on écrit les règles du projet. Le repo en a un par sous-projet : l’app, les dictionnaires, le site, le marketing. Chacun dit comment builder, tester et déployer, et surtout ce qu’il ne faut jamais refaire.
La partie la plus utile, c’est la section « Known issues ». Chaque ligne est une erreur qui a coûté au moins un build. Un extrait :
| Piège | Conséquence | Parade |
|---|---|---|
LIMIT sans ORDER BY sur Wikidata | Deux runs ne renvoient pas le même sous-ensemble | Fusionner avec l’existant, ne jamais remplacer |
| Une requête qui fail sans erreur | Le script écrit un fichier tronqué par-dessus le bon | Guardrail : refuser d’écrire si le corpus maigrit |
| Deux builds iOS en parallèle | expo prebuild --clean sur le même ios/, les deux échouent | Un seul build à la fois |
LOWER() de SQLite sur un mot à capitale accentuée | LOWER('Écoute') reste Écoute : 6 149 questions de quiz invisibles | Comparer des colonnes déjà normalisées (casefold) en Python |
Quand une erreur arrive, on la corrige, puis on l’écrit. La session suivante ne la refait pas. C’est le vrai mécanisme d’apprentissage du projet : pas le modèle, le fichier.
À côté, Claude garde une memory d’une session à l’autre : une note par fait non évident (« FTS5 n’existe pas dans le SQLite d’Android », « le track internal du Play Store ne vérifie pas l’alignement 16 Ko »), avec le pourquoi et la façon de l’appliquer.
2. Les données : neuf dictionnaires
C’est la plus grosse partie du code : environ 49 600 lignes de Python, contre 33 000 pour l’app et 14 400 pour le site.
Les sources sont publiques : Wiktionnaire, Wikidata, la base Lexique pour les fréquences d’usage. Claude écrit les scripts d’extraction, puis rédige lui-même les définitions, en batch, avec la Batch API d’Anthropic (moitié prix, résultat dans la journée). Pour le français général, chaque mot reçoit sept définitions, une par niveau.
La Batch API mérite qu’on s’y arrête : c’est elle qui rend le projet abordable. On envoie des milliers de requêtes d’un coup, Anthropic les traite dans les 24 heures (souvent bien moins), et la facture est divisée par deux. Pour un dictionnaire, l’attente ne gêne personne : on lance un batch le soir, on fusionne le résultat le lendemain.
Les chiffres du dictionnaire d’intelligence artificielle, tirés du changelog du projet :
- 2 628 termes, quatre niveaux de lecture chacun et 7 293 QCM : 10 batches, environ 75 $ au total ;
- avant la production, deux batches de test de 10 termes, pour 0,40 $. Ils ont révélé trois défauts du prompt, dont un niveau expert 35 % trop court ;
- la réécriture des niveaux avancé et expert de 2 727 définitions : 98,46 $.
Deux réglages ont compté autant que la remise :
- réécrire plutôt que régénérer : on repasse le texte existant en input, et un token d’input coûte cinq fois moins cher qu’un token d’output ;
- un effort
mediumplutôt quehigh: le thinking pesait 58 % de l’output facturé. Sur trois batches de test, l’efforthighcoûtait 157 $, pour un résultat moins bon.
Les faits, eux, ne sont jamais générés. La capitale d’un pays, sa monnaie, sa population viennent de Wikidata. Et Wikidata a ses pièges, qui sont tous dans le CLAUDE.md aujourd’hui :
- la France avait pour capitale « Alger, Bayeux, Bordeaux » : la requête remontait aussi les valeurs historiques. Il faut exclure celles qui portent une date de fin (propriété
P582) ; - l’euro s’affichait
Q4916: Wikidata a déplacé une partie de ses labels vers un code de languemul. Les requêtes demandent maintenantfr,mul,en, et un label de la formeQsuivi de chiffres est rejeté.
Les quiz sortent d’une pipeline en cinq étapes, et chaque étape repart de là où elle s’est arrêtée en cas d’interruption : filtrer les mots, faire juger les candidats par Claude, planifier les types de questions, générer, fusionner. Chaque question a un ID stable : on la retrouve d’une génération à l’autre.

3. L’app
L’app est en React Native avec Expo. Le dictionnaire général pèse 138 Mo en SQLite. Le copier au premier lancement prenait une minute : un module natif, en Swift et en Kotlin, l’ouvre directement en lecture seule depuis l’app. Le premier lancement est instantané.
Ce module a sa propre histoire. La recherche full-text utilise FTS5, une extension de SQLite. iOS l’a. Android non : le SQLite du système est compilé sans. Claude a donc compilé SQLite lui-même, avec FTS5, dans le module Android.
Puis, en août, le Play Store a refusé la release en production : « Artifact does not support 16KB page size ». Sur les 24 libs natives de l’app, une seule n’était pas conforme : notre SQLite compilé maison, aligné sur 4 Ko. Le fix tient en une ligne de CMake :
target_link_options(dicode_sqlite PRIVATE "-Wl,-z,max-page-size=16384")
Le piège : le track internal du Play Store ne vérifie pas cette règle. L’upload passait sans erreur, et seule la release en production échouait.
L’app a un mode clair et un mode sombre. Pour qu’aucune couleur en dur ne pose problème dans l’un des deux, une règle ast-grep refuse les couleurs littérales dans les composants. La règle a ses angles morts (une couleur construite par concaténation lui échappe), et le CLAUDE.md les liste.
4. Le site
Le site https://dicode.fr est construit avec Astro : 94 069 pages de mots pré-générées (SSG), hébergées sur S3 derrière CloudFront, avec toute l’infrastructure décrite en OpenTofu. Quand un visiteur cherche un mot qui n’a pas encore de définition, une Lambda la fait rédiger par Claude à la volée, la stocke sur S3, et elle devient une page statique au déploiement suivant.
Le SEO nous a appris une chose. Pour choisir les pages à mettre dans le sitemap, la première idée était un seuil de fréquence d’usage. Mesuré sur 16 mois de données Search Console, ce seuil aurait retiré du sitemap des pages qui portaient 59 % des impressions du site. On ne cherche pas la définition des mots courants : on cherche celle des mots qu’on ne connaît pas. Le sitemap retient maintenant les mots que les gens cherchent vraiment.
5. Les tests
Environ 1 500 tests automatiques : 681 tests unitaires et 466 tests d’intégration dans l’app, 151 sur le site, environ 200 en Python sur les données, et 7 flows Maestro qui pilotent l’app sur simulateur.
Les flows Maestro ont donné la leçon la plus utile. Trois d’entre eux passaient en validant un geste que personne n’avait fait. tapOn: "mémoire" touchait le champ de saisie, pas le résultat de recherche : le flow ne prouvait rien, et un bug est resté des mois sans être vu. La règle depuis : après chaque tap, vérifier quelque chose que seul l’écran visé affiche.
6. Les stores
Tout est buildé en local sur le Mac, sans service de build payant : un script pour l’IPA iOS, un pour l’AAB Android, puis fastlane pour l’upload vers TestFlight, l’App Store et le Play Store. La version 1.30.4 porte le build 104, le même numéro sur iOS et sur Android.
Une règle vient d’un testeur qui ne savait pas quoi tester : chaque build TestFlight doit dire quoi tester. Sans release notes, fastlane envoyait « New build from Fastlane », et le testeur ouvrait l’app sans savoir quoi regarder. La lane refuse maintenant de publier sans le fichier de release notes. Elle refuse aussi le grec polytonique dans ces notes (ἀ, ῳ) : App Store Connect le rejette, mais seulement après l’upload et le traitement du build.
7. Ce qui a foiré
Tout est dans l’historique Git :
- le feed ne passait pas au mot suivant. Chaque définition avait son propre scroll, imbriqué dans le scroll du feed. Une fois en bas d’une définition, iOS ne transmettait pas le geste : pendant 1,25 seconde, le doigt bougeait et l’écran non (mesuré sur vidéo). J’avais dit dès le début que chaque définition défilait « comme dans une iframe ». Plusieurs fixes ont traité les symptômes avant qu’on supprime la cause : il n’y a plus qu’un seul scroll ;
- la liste des dictionnaires ne scrollait presque pas sur Android. Elle débordait de son bandeau, et Android ne transmet un geste à un élément que s’il est à l’intérieur de son parent. Les taps passaient, pas le scroll. Elle s’ouvre maintenant dans une modale ;
- 242 mots avaient une mauvaise URL sur le site : « cœur » avait l’URL
/mot/c-ur/, et « œil »/mot/il/, la même que le pronom. La lettre œ disparaissait au lieu de devenir « oe ». Corrigé, avec 244 redirections depuis les anciennes URL ; - la release Android en production bloquée par l’alignement 16 Ko, décrite plus haut ;
- deux builds iOS lancés en parallèle ont planté tous les deux, alors que Claude les annonçait OK ;
- une commande de déploiement terminée par
| tailpouvait fail sans erreur : l’exit code était celui detail. Les commandes qui comptent écrivent maintenant leurs logs dans un fichier.
8. Ce que Claude ne fait pas
- tester sur un vrai téléphone : c’est moi qui fais défiler, qui sens qu’un geste accroche, qui vois qu’un texte est illisible en mode nuit ;
- relire le contenu : une source publique donnait Alger comme capitale de la France. L’erreur a été repérée et corrigée avant d’arriver dans l’app, mais il faut quelqu’un pour la voir ;
- trancher : le prix des dictionnaires, ce qui entre dans l’app, ce qu’on publie. Claude propose, je décide ;
- les comptes : Apple, Google, le domaine, le paiement de l’API. Claude ne crée pas de compte et ne saisit pas de mot de passe.
Les chiffres
| Durée | du 1er février au 19 octobre 2026 |
| Commits | 649 |
| Code | environ 99 000 lignes : 49 600 de Python, 38 700 de TypeScript, 2 800 d’Astro, 1 800 d’OpenTofu, un peu de Swift et de Kotlin |
| Documentation | environ 36 000 lignes de Markdown |
| Tests | 681 unitaires et 466 d’intégration (app), 151 (site), environ 200 en Python, 7 flows Maestro |
| Contenu | 9 dictionnaires, 240 592 questions de quiz, 94 069 pages sur le site |
| Versions | 1.30.4, build 104, sur l’App Store et le Play Store |
Ce que l’on peut en retenir
Le CLAUDE.md compte plus que le prompt. Un prompt brillant sert une fois. Une ligne dans les known issues sert à chaque session suivante. Chaque erreur ne se fait qu’une fois, à condition de l’écrire tout de suite, pendant qu’on sait encore pourquoi elle est arrivée.
Claude écrit le code vite, mais il faut tester sur un vrai téléphone. Le feed qui accrochait pendant 1,25 seconde, aucun test ne l’a vu. Je l’ai senti en faisant défiler l’app sur mon téléphone. Sur ce projet, ce qui ralentissait n’a jamais été l’écriture du code, mais le temps passé à tester l’app à la main.
Un test qui passe ne prouve que ce qu’il vérifie. Trois flows Maestro passaient sans rien prouver. Depuis, je ne demande plus « les tests passent ? », mais « qu’est-ce que ce test aurait vu en cas de régression ? ».
Les faits viennent de sources, jamais du modèle. Claude rédige très bien une définition pour un élève de CP. Ce n’est pas à lui de décider de la capitale de la France. Tout ce qui peut être vrai ou faux vient de Wikidata ou du Wiktionnaire, et des guardrails refusent d’écrire un fichier plus petit que le précédent.
Enfin, ne pas écrire de code ne veut pas dire ne pas travailler. Je n’ai jamais autant spécifié, relu, testé et tranché. Le métier change, il ne disparaît pas.
Liens
- Dicode sur l’App Store : https://apps.apple.com/app/id6759469805
- Dicode sur le Play Store : https://play.google.com/store/apps/details?id=com.nuagic.dicode
- Le site : https://dicode.fr
- Nuagic : https://nuagic.com
- Mon blog : https://heurisme.fr