📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

~7 min de lecture

J'ai refondu la landing EasyAngularKit avec impeccable, voici ce que ça donne

J'ai un site Angular en prod, easyangularkit.com. Tech solide (Angular 21 SSR + Nx + Tailwind v4), mais je sentais que le design avait un problème : il sentait le template SaaS AI-généré moyen. Inter + Space Grotesk + JetBrains Mono partout, glassmorphism décoratif, hero centré icon-title-CTA, grilles 3 colonnes répétées. Pas catastrophique, mais pas non plus distinctif. Or je vends une formation premium — ma landing doit être à la hauteur.

J'ai testé une skill open-source qui s'appelle impeccable. Voici le retour brut, avec les chiffres, les commits et les pièges.


L'outil : impeccable

impeccable.style (GitHub), par Paul Bakaus. C'est une skill compatible Claude Code, Cursor, Codex CLI, Gemini CLI. Une skill = un ensemble cohérent d'instructions injectées dans le contexte de l'agent.

Concrètement, impeccable apporte :

  • 23 sous-commandes design : audit, typeset, colorize, quieter, layout, harden, polish, etc.
  • Une liste codifiée d'anti-patterns : typographies "reflex-reject" (Inter, DM Sans, Cormorant…), glassmorphism par défaut, side-stripe borders, gradient text, em dashes, hero-metric template…
  • Un protocole strict : avant toute commande, l'agent doit charger PRODUCT.md (stratégie marque) et DESIGN.md (système visuel). Sans PRODUCT.md, l'audit refuse de tourner.

Installation

npx skills add pbakaus/impeccable --yes

Crée .agents/skills/impeccable/ avec :

  • SKILL.md : entrée principale, règles globales, routing des commandes
  • reference/*.md : 23 fichiers de spec, un par sous-commande
  • scripts/*.mjs : utilitaires (load-context, pin/unpin)

Le protocole imposé

Chaque sous-commande passe par des "gates" :

  1. Context gatenode .agents/skills/impeccable/scripts/load-context.mjs charge PRODUCT.md + DESIGN.md
  2. Product gatePRODUCT.md doit exister, sinon $impeccable teach est invoqué (interview courte)
  3. Command gate — la spec de la commande appelée doit être chargée

Avant le premier $impeccable audit, j'ai dû créer PRODUCT.md via une interview de 4 questions (registre brand vs product, 3 mots de personnalité, références visuelles, niveau d'a11y visé). Mes réponses : brand / "expert, direct, premium" / Linear-Vercel-Stripe / WCAG 2.1 AA. Ces réponses conditionnent tout l'audit qui suit — elles servent de filtre opinionnated pour distinguer un anti-pattern vrai d'un anti-pattern de circonstance.


Le déroulé chronologique

Phase 0 — Setup

npx skills add pbakaus/impeccable --yes

Skill installée + PRODUCT.md créé après interview.

Phase 1 — Audit initial

$impeccable audit

L'audit ne modifie rien. Score : 10/20 (D+ — Acceptable). Il a sorti une liste de findings :

  • P0 Typographie reflex-reject (Inter / Space Grotesk / JetBrains Mono — les trois explicitement bannies)
  • P0 Glassmorphism prolifique (28 backdrop-filter cumulés)
  • P0 transition: width sur la barre de progression de lecture (layout thrash à chaque scroll)
  • P0 Em dash dans la copy
  • P1 outline: none / :focus-visible incomplets
  • P1 Hex hardcodés contournant les tokens CSS
  • P1 Hero centré template
  • P1 Grilles 3-cols répétées
  • P1 Contraste insuffisant light-blue sur fond clair
  • P1 overflow-x: hidden à 3 niveaux

Phase 2 — Application des recommandations

Une commande, un commit. Dans l'ordre P0 → P1 → P2 :

# Commande Effet
1 $impeccable optimize Barre de progression widthtransform: scaleX. Blurs plafonnés à 12-16 px.
2 $impeccable clarify Em dash + typos congrats.page.ts.
3 $impeccable harden :focus-visible global, prefers-reduced-motion global, hex tokenisés.
4 $impeccable adapt overflow-x: hidden redondants retirés, touch targets 44 px + aria sur tag-filters.
5 $impeccable quieter Glassmorphism réduit à 1 surface (la navbar). 28 → 2 occurrences.
6 $impeccable colorize Token --color-link-blue (#3a6fa5, AA sur blanc), --color-white teinté, jaune décoratif retiré.
7 $impeccable typeset Inter / Space Grotesk / JetBrains Mono → Cabinet Grotesk + Switzer + Geist Mono. ~6 Mo de fonts orphelines supprimées.
8 $impeccable layout why-angular : grille 3-cols → liste-spécimen numérotée asymétrique.
9 $impeccable shape + bolder Hero centré → asymétrique 2 colonnes (texte gauche, vidéo droite).
10 $impeccable document Génération de DESIGN.md (format Stitch, 6 sections normatives).
11 $impeccable polish Tokens CSS obsolètes supprimés, CLAUDE.md aligné.

Phase 3 — Bugs découverts en preview Vercel

L'audit ne testait pas le rendu réel. Premiers déploiements ont révélé :

Bug Cause
Carré clippé en haut à gauche sur mobile background-attachment: fixed sur body — bug iOS Safari
Fond redevenu blanc html::before ne propageait pas au canvas — gradient remis sur html direct
Hero suivi directement du footer @defer (on idle) ne firait pas (CDN fonts maintenaient la page non-idle) → migration vers withIncrementalHydration() + hydrate on viewport / hydrate on timer(2s)
Photo Gaëtan en broken-image icon <picture><source> + NgOptimizedImage créait un conflit d'hydratation. Final : <img> natif simple
Pastilles dark-blue sur fond glass-card dark-blue Disques navy invisibles. Remplacés par icônes outline jaune flush
Testimonials coupé / lent iframeResizer injecté tardivement. Final : <script async> dans index.html + min-height: 480px + preconnect
Code inline qui déborde des titres blog Trois itérations pour trouver le bon équilibre : pastille sombre conservée + line-height: 1.3 heading + chip compressé
Lead atout sur 3 lignes mobile Stack vertical mobile / grid 2-col desktop

Phase 4 — Re-audit

$impeccable audit

Score : 16/20 (+6, "Good"). 4 P1 restants identifiés.

Phase 5 — Application des P1 restants

# Commande Effet
1 $impeccable harden Bug class="..." + [class]="..." sur même élément (le statique écrasé), focus:outline-none retiré
2 $impeccable optimize Hero iframe loading="eager", floating-emojis.ts supprimé (code mort, 15 nœuds DOM par page)
3 $impeccable colorize Yellow density sur wall-of-love : 4 → 2 backgrounds
4 $impeccable layout border-l-4 border-primary-yellow (side-stripe banni) → bordure 1px hairline + jaune au hover
5 $impeccable polish 9 tokens CSS morts retirés

Phase 6 — Audit final

Score : 19/20 ("Excellent — minor polish"). Le seul P2 restant est un bundle JS à 595 kB (warning band, pas blocker).


Les chiffres

Métrique Avant Après Δ
Score $impeccable audit 10/20 19/20 +9
Familles typographiques reflex-reject 3/3 0/3 -3
Surfaces glassmorphism 28 1 -27
bg-primary-yellow décoratifs (≥ 32 px hors CTA) 13 5 -8
Tokens CSS morts 18 0 -18
Self-hosted font files ~6 Mo 0 -6 Mo
Side-stripe borders 1 0 -1
Em dash dans le code 1 0 -1
Hardcoded hex colors dans composants ~20 0 -20
outline: none non remplacé 2 0 -2
Code net (.ts + .css) -503 lignes

Le top 3 de ce qui change vraiment

1. La typographie

Avant : Inter (corps) + Space Grotesk (titres) + JetBrains Mono (code) — exactement la signature de 80 % des landings AI-générées.

Après : Cabinet Grotesk + Switzer (Fontshare, gratuit) + Geist Mono (Google Fonts). Hors reflex-reject list, plus distinctif.

<!-- index.html -->
<link rel="preconnect" href="https://api.fontshare.com" crossorigin>
<link rel="preconnect" href="https://cdn.fontshare.com" crossorigin>
<link rel="stylesheet" href="https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@500,600,700,800&f[]=switzer@300,400,500,600,700&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600&display=swap">

2. Le hero

Avant : centré icon-title-subtitle-CTA, video en glass-premium sous le tout. Template.

Après : grille asymétrique 1.05fr / 1fr — texte à gauche (eyebrow formation angular · v18 → v21, titre Cabinet Grotesk 8vw, sous-titre, CTA), vidéo YouTube à droite. Stack vertical sur mobile.

3. L'incremental hydration

Découverte forcée par un bug : @defer (on idle) ne firait jamais sur certaines sessions iOS Safari à cause des nombreux scripts tiers (analytics, Stripe, Hotjar, GTM, testimonial.to…). Migration vers :

// app.config.ts
provideClientHydration(withEventReplay(), withIncrementalHydration())
// landing.page.ts
@defer (hydrate on viewport; hydrate on timer(2s)) {
  <app-why-angular />
  <!-- ... -->
}

Toutes les sections sont SSR-rendered (visibles dès le premier paint), l'hydratation JS arrive ensuite quand le déclencheur fire.


Les apprentissages

  1. Sans PRODUCT.md et DESIGN.md, l'agent fait du générique. Les deux fichiers obligent à fixer les anti-références ("ce que je ne veux PAS être") et les principes — c'est ça qui transforme l'audit générique en audit opinionnated.

  2. Le protocole de gates oblige à ralentir. Avant chaque commande, le contexte doit être chargé. Ça force à séquencer les passes plutôt que tout faire en parallèle.

  3. L'audit n'est pas un test visuel. Il scanne le code — il ne voit pas iOS Safari, le bundle réel sur device, les hydration mismatches. La phase 3 (debug post-deploy) est inévitable et ne remet pas en cause la qualité du diagnostic initial.

  4. Le score 19/20 n'est pas une fin. C'est un signal que les anti-patterns codifiés sont éliminés. Les vrais tests d'usage (Lighthouse, A/B, conversion) restent à faire indépendamment.

  5. Beaucoup de "fixes" sont des reverts. La phase 3 a vu plusieurs commits qui détricotent des choix de la phase 2 (pastilles inline-code, photo wrapper, defer trigger). Itération > planification parfaite.


Reproductibilité

Si tu veux refaire ce travail sur un autre projet :

# 1. Installer la skill
npx skills add pbakaus/impeccable --yes

# 2. Charger le contexte (dans Claude Code)
node .agents/skills/impeccable/scripts/load-context.mjs

# 3. Si pas de PRODUCT.md
# $impeccable teach

# 4. Audit
# $impeccable audit

# 5. Appliquer chaque recommandation, un commit par commande
# $impeccable typeset / quieter / colorize / layout / harden / optimize / clarify / adapt / polish

# 6. Document quand le système est stable
# $impeccable document

# 7. Re-audit pour valider
# $impeccable audit

Verdict

impeccable n'est pas une baguette magique. C'est un filtre opinionnated qui transforme l'agent en designer-junior sérieux : il ne va pas inventer de génie créatif, mais il va éliminer les 5 ou 6 tells qui font qu'une landing ressemble à 1000 autres. Pour un projet comme EAK où "le design est un argument de preuve", c'était exactement ce qu'il fallait.

Score 10/20 → 19/20 en 28 commits, étalés sur quelques sessions. Si tu vends quelque chose en ligne et que ta landing date de plus d'un an sans refonte, tu vas trouver des choses.


🎁 Et si tu veux voir le résultat en vrai : easyangularkit.com

📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

AngularKit

Suite d'outils pour développeurs Angular francophones. Apprends, modernise tes réflexes, audite ta codebase.

Produits

Contact

Légal

© 2026 AngularKit. Tous droits réservés.