Revue de neural-slop
Le neural-slop n'est pas une question de style, mais d'affirmations non vérifiées et de code sans raison d'exister. Chaque constat ci-dessous est vérifié par un fait : une ligne de code, la sortie d'une commande, l'absence de consommateur. Les remarques de goût et ce qu'attrape un linter ne sont pas inclus.
Principes.
- Supprimer vaut mieux qu'ajouter. Une option morte est supprimée, pas documentée ; une phrase marketing est remplacée par un fait ou retirée.
- L'affirmation est vérifiée par le code, pas par mémoire. Avant de dire qu'une ligne du README est fausse ou vraie, ouvre le fichier dont elle parle.
- Un constat sans preuve n'est pas un constat. Si tu ne peux pas montrer
fichier:ligneou la sortie d'une commande, n'écris pas. - Les corrections sont faites uniquement sur demande. Par défaut, le résultat de la revue est une liste.
1. Déroulement du travail
- Définis le périmètre : diff (
git diff main...HEAD), fichiers spécifiques ou tout le dépôt avant publication. - Exécute la recherche de la section 3 — elle donne des candidats, pas des constats.
- Vérifie chaque candidat en lisant le code et écarte les faux positifs.
- Parcours la checklist de la section 2 pour ce que la recherche ne détecte pas : README vs code, états UI, abstractions.
- Si possible de lancer l'application, regarde les pages : les écrans modèles et les composants non stylisés sont visibles immédiatement.
- Produis un rapport au format de la section 4.
2. Checklist
2.1. Vestiges de générateurs et de modèles
- Pages de démarrage et blocs de générateurs : « Get started by editing », liens vers la documentation du framework et des outils,
utm_source=…-project, « Give us a star », blocs sur les services cloud de l'outil. - Fichiers modèles :
example.spec.ts, tests qui ne vérifient que le titre du modèle ; SVG et images du modèle danspublic/; README du générateur. - Placeholders vides :
.gitkeepdans des dossiers contenant déjà des fichiers ;index.tsvides ; dossiers-couches sans code.
2.2. Éléments morts et inachevés
- Valeurs de configuration ou branches
switchqui lèvent « not implemented » / « pending ». - Énumérations avec une seule valeur qui ressemblent à des points d'extension (
type: "graphql" | "msw", oùmswn'est pas implémenté). - Code commenté,
TODOsans raison ni lien, exports inutilisés, dépendances danspackage.jsonqui ne sont importées nulle part. - Scripts dans
package.jsonqui ne s'exécutent pas (références à des fichiers supprimés, à des cibles inexistantes).
2.3. Documentation contre code
Chaque affirmation du README, des ADR, des commentaires et des descriptions de commits est vérifiée :
- Noms et chemins : les fichiers, commandes, variables d'environnement mentionnés existent (
next.config.tsdans le texte etnext.config.jsdans le dépôt est un constat). - Comportement : « les requêtes vont directement », « les tokens ne sont pas accessibles en JS », « protégé contre l'open redirect » — trouve le code qui fait cela et vérifie les cas limites.
- Versions et chiffres : versions des bibliothèques, durée de vie des tokens, couverture.
- Futur au présent : ce qui est planifié est décrit comme réalisé.
- Les liens et ancres Markdown pointent là où ils doivent (les ancres se cassent lors de la modification des titres).
2.4. Ton
- Mots évaluatifs au lieu de faits : premium, state-of-the-art, cutting-edge, blazing/lightning-fast, seamless, robust, powerful, modern, production-ready, enterprise-grade, « plus qu'un simple », « premium », « moderne », « puissant ».
- Emojis dans les titres de documentation, l'UI, les logs et les messages de commit.
- « Designed with ❤️ », « Carefully crafted », badges pour les badges.
- Commentaires-redites (« // Récupère l'utilisateur » au-dessus de
getUser()), commentaires-historique (« // Corrigé », « // Mis à jour vers X »), commentaires en majuscules, marques « IMPORTANT » sans explication. - Titres et commentaires de type « 🚀 Production Roadmap » et « (Premium Aesthetic) ».
Remplacement — un fait : ce que ça fait, pourquoi c'est ainsi, quelle est la limitation.
2.5. Abstractions superflues
- Interface ou fabrique avec une seule implémentation et sans faux dans les tests.
- Couche, zone, package de monorepo, gestionnaire d'état, Storybook sans consommateur ou sans raison documentée (ADR, section README).
- Wrappers qui ne font que renommer (
useAuthApi = () => useStrictContext(Ctx)sans logique — acceptable ; un wrapper autour d'un wrapper — non). - « Pour le futur » : paramètres que personne ne passe, options de configuration avec une seule valeur.
2.6. Erreurs et asynchronisme
- Le type d'erreur est déterminé par le texte du message (
message === "unauthorized",includes("invalid password")) — sans commentaire de raison ni tests. - Seul le premier élément du tableau d'erreurs est vérifié (
errors[0]). throw { status, ... }— un objet au lieu d'Error.catchvide,catchqui retourne des données vides,.catch(() => {}).- Promesse partagée in-flight dont les waiters ne lisent pas le résultat (rafraîchissement de token « on attend, puis on réessaie » sans vérifier s'il a réussi).
error.messagedu serveur affiché tel quel à l'utilisateur.- Absence d'états de chargement, d'erreur, de liste vide.
2.7. Sécurité et vie privée
- Données personnelles dans les logs : email, téléphone, nom ; tokens ; corps de requêtes.
- Secrets dans le dépôt ou dans l'historique (
git log -p),.envdans l'index, secrets avec le préfixeNEXT_PUBLIC_. - Redirections basées sur un paramètre (
callbackUrl,next,returnTo) sans vérification, ou avec une vérification uniquement parstartsWith("/")/!startsWith("//")— laisse passer/\evil.comet les caractères de contrôle. - Tokens dans
localStorage/sessionStorage; token dans l'URL qui n'est pas supprimé de la barre d'adresse après lecture. dangerouslySetInnerHTMLsans sanitizer.
2.8. UI
- Classes qui n'existent pas dans le thème : tokens copiés de shadcn/ui (
bg-card,text-muted-foreground,bg-primary) dans un projet dépourvu de ces tokens — le composant est muet, sans styles. - Valeurs HEX brutes et valeurs arbitraires dans les composants alors que des tokens existent.
- État « champ rempli » défini dans
onChange: cassé par l'autocomplétion etreset(). key={index}dans des listes modifiables ; boutons sanstypedans des formulaires ; boutons-icônes sansaria-label.- SVG provenant de la maquette avec des filtres (ombres, lueurs) tronqués par
viewBox— rectangle visible autour du logo.
2.9. Tests
- Tests qui vérifient les mocks, pas le comportement ; snapshots de grands arbres.
- e2e contre un backend commun ou de production, modifiant les données.
- Tests qui passent uniquement parce que jsdom n'applique pas le CSS (élément « caché » par une classe, mais le test le trouve) et sélecteurs trop larges (
/password/i, qui correspond aussi à « Show password »).
2.10. Git
- Modifications sans rapport dans un même commit ; commit « fix stuff ».
- Fichiers générés et artefacts de build dans l'index (sauf client API généré sciemment commité).
- Le message de commit ne décrit pas ce qui est dans le diff.
3. Recherche de candidats
Les commandes donnent des candidats. Chaque correspondance est vérifiée en lisant le code.
# Modèles de générateurs et marketing
rg -n -i "utm_source|get started by editing|give us a star|nx cloud|welcome to|carefully crafted|designed with" \
--glob '!**/node_modules/**' --glob '!*.lock' --glob '!pnpm-lock.yaml'
rg -n -i "premium|state-of-the-art|cutting-edge|blazing|lightning|seamless|robust|enterprise-grade|production-ready|premium|moderne|puissant" \
--glob '!**/node_modules/**'
# Emojis dans le code, l'UI et la documentation
rg -n --pcre2 '[\x{1F300}-\x{1FAFF}\x{2600}-\x{27BF}]' --glob '!**/node_modules/**' --glob '!*.lock'
# Inachevé
rg -n -i "not implemented|pending implementation|todo|fixme|hack" --glob '!**/node_modules/**'
# Erreurs fragiles
rg -n "errors\?\.\[0\]|errors\[0\]|message ===|message\.includes|\.includes\(['\"][a-z ]+['\"]\)" src app
rg -n "throw \{" src app
rg -n "catch \{\s*\}|catch \(\w*\) \{\s*\}|\.catch\(\(\) => \{\s*\}\)" src app
# Logs avec données personnelles
rg -n "(logger|console)\.\w+\(.*(email|phone|password|token)" src app
# Redirections et tokens
rg -n "callbackUrl|returnTo|redirectTo|searchParams.get\(['\"]next" src app
rg -n "localStorage|sessionStorage" src app
# Classes shadcn sans tokens : trouve les classes et vérifie avec @theme / config tailwind
rg -n -o "\b(bg|text|border)-(card|muted|popover|accent|primary|secondary|destructive)(-foreground)?\b" src app | sort -u
# Dépendances et exports inutilisés (si knip est installé)
pnpm dlx knip
# Secrets dans l'historique
git log -p --all | rg -n -i "(api[_-]?key|secret|password|token)\s*[:=]\s*['\"][A-Za-z0-9_\-]{16,}"
git ls-files | rg -n "(^|/)\.env($|\.)" | rg -v "\.env\.example$"
4. Format du rapport
Les constats — par ordre décroissant d'importance : sécurité et vie privée → affirmations fausses dans la documentation → bugs de gestion d'erreurs → éléments morts et inachevés → modèles → ton.
<fichier>:<ligne> — <catégorie>
Quoi : <une phrase : ce qui ne va pas, avec un fait>
Pourquoi c'est important : <conséquence pour l'utilisateur, le relecteur ou la maintenance>
Correction : <concrètement ; le plus souvent « supprimer » ou « remplacer par un fait : … »>
À la fin — ce qui a été vérifié et n'a donné aucun constat, et ce qui n'a pas été vérifié (par exemple, l'application n'a pas été lancée). S'il n'y a aucun constat, dis-le simplement, sans remarques forcées.