À compléter avant l'envoi
[server name][year][organisation name][what it does, where, founding year][one sentence][figure, unit, one-sentence explanation][for each chart, title, periods and values][income sources and expense lines, amounts and shares][chapter names and the text or notes for each][items][which records, how missing data was handled][editor's name, date]
Sur mon serveur d'hébergement Opus Growth [server name], construis le rapport d'impact [year] de [organisation name] sous la forme d'un site qui raconte son histoire au fil du défilement. Organisation : [what it does, where, founding year]. Message principal du rapport : [one sentence]. Les quatre chiffres clés : [figure, unit, one-sentence explanation]. Données des graphiques : [for each chart, title, periods and values]. Budget : [income sources and expense lines, amounts and shares]. Chapitres : [chapter names and the text or notes for each]. Plan de l'année prochaine : [items]. Origine des chiffres et leurs limites : [which records, how missing data was handled]. Rédigé par et date de publication : [editor's name, date]. Contact : [email], [phone], [address]. Domaine : [domain]. Photos : [links; no faces of children or beneficiaries].
Pages : rapport (/ : titre de couverture, paragraphe de synthèse qui donne la réponse d'emblée, auteur et date, image de couverture, navigation de chapitres collante et, dans l'ordre, synthèse de l'année, chapitres, budget, plan de l'année prochaine et questions sur le rapport), méthodologie (/yontem/ : la source et les limites de chaque chiffre), organisation et contact (/dernek/ ou un nom adapté à votre organisation), confidentialité et KVKK (/gizlilik/) et 404.html. Écris les graphiques en SVG statique généré à partir des valeurs que je t'ai données, sans Chart.js ni D3 ; n'arrondis pas les valeurs et vérifie que les totaux concordent. Affiche le budget sous forme de `<table>` sans largeur minimale, pas sous forme de graphique.
Style : une lecture longue façon data story de presse. Fond ton papier, une police serif Fontshare pour les titres (par exemple Bespoke Serif) et une police de texte lisible qui prend en charge tabular-nums (par exemple Epilogue), avec au maximum deux couleurs de graphique. Sur ordinateur, une liste de chapitres collante de 220 px à gauche ; sur mobile, une bande de chapitres à défilement horizontal collée en haut, avec une fine ligne de progression de lecture dessous.
Règles d'animation (la partie la plus difficile, à suivre à la lettre) :
1. Bibliothèques : uniquement le cœur de GSAP 3.13 et ScrollTrigger, uniquement sur la page du rapport. Lenis n'est PAS chargé, car le défilement natif est plus confortable pour une lecture longue ; SplitText et les bibliothèques de graphiques ne sont pas chargés non plus. Aucun script sur les pages méthodologie, organisation et confidentialité.
2. Graphiques linéaires : chaque ligne est un `<path pathLength="1">` entièrement tracé dans le HTML. Le JS applique strokeDasharray 1 et strokeDashoffset 1 uniquement aux graphiques situés sous l'écran au chargement, puis ramène l'offset à 0 avec le scrub de ScrollTrigger (start "top 75%", end "bottom 65%") ; les points de données apparaissent progressivement au passage de la ligne. Mets le texte SVG à au moins 22 unités dans un viewBox de 600 unités pour qu'il reste au-dessus de 12 px sur mobile, et laisse au moins 40 unités à droite pour que la dernière étiquette d'axe ne soit pas coupée.
3. Chaque graphique est un `<svg role="img" aria-labelledby>` avec un title et un desc qui énonce toutes les valeurs en une phrase ; la figcaption indique la source et renvoie vers la note méthodologique, et IMMÉDIATEMENT APRÈS la figure, un `<details>` intitulé "Voir les données sous forme de tableau" contient un vrai `<table>`. Ce tableau est la version texte des données, à la fois pour l'accessibilité et pour la recherche par IA.
4. Compteurs : la valeur finale est écrite dans le HTML au format turc (par exemple 31.540). Le nombre visuel se trouve dans un span aria-hidden et la même valeur dans un span sr-only pour les lecteurs d'écran. Le JS remet à 0 uniquement les compteurs situés sous l'écran au chargement et les fait compter avec Intl.NumberFormat("tr-TR") quand ils entrent à l'écran ; ne jamais remettre à zéro un nombre déjà visible. Applique tabular-nums au nombre et une largeur minimale égale au nombre de caractères de la valeur finale (avec une classe Tailwind, pas un attribut style) pour que la ligne ne bouge pas pendant le comptage.
5. Navigation de chapitres : les liens sont des ancres qui fonctionnent sans JS. Le JS utilise ScrollTrigger par chapitre pour trouver le chapitre actif, place aria-current="true" sur son lien et fait défiler la bande mobile latéralement pour que le lien actif soit visible (la bande, pas la page). Place le comportement collant sur la barre latérale (aside), enfant direct de la grille qui couvre tout le rapport, et non sur le nav interne ; dans la démo, le sticky sur le nav interne ne collait jamais sur mobile.
6. Aucune autre animation en dehors de la ligne de progression de lecture et des images qui apparaissent avec data-reveal.
Mise en place et pièges connus (chacun a couté des points ou cassé quelque chose lors de la mesure de la démo, n'en saute aucun) :
1. S'il existe déjà un site en ligne sur le serveur, dis-le-moi d'abord, car l'installation écrase index.html et le dossier assets. Prévisualise scaffold_site avec confirm=false et appelle confirm=true après mon accord. Lis ensuite site_design_guide et site_seo_guide. Avant d'écrire du code, mets la direction de design (typographie, couleur, grille, élément signature, langage d'animation et bibliothèques qui ne seront PAS chargées) dans un court ART.md en dehors d'assets et montre-le-moi.
2. Compile Tailwind, ne le charge pas depuis le CDN. Installe `npm i -D tailwindcss@3` avec site_run_command et background=true, et suis-le avec site_command_status. Les chemins content de `tailwind.config.js` doivent couvrir tous les fichiers HTML, tous les templates et tous les fichiers JS qui écrivent des classes. `_src/tw.css` contient une ligne `@import "../assets/app.css";` et les trois lignes `@tailwind` ; compile-le dans un seul fichier avec `npx tailwindcss -c tailwind.config.js -i _src/tw.css -o assets/site.css --minify`. Retire le script cdn.tailwindcss.com et le tailwind.config en ligne des pages et ne lie que `/assets/site.css`. Recompile après chaque modification du HTML.
3. Héberge les polices toi-même. Vérifie d'abord que la famille Fontshare choisie contient les lettres turques (ş, ğ, ı, İ, ç, ö, ü) : dans la démo, Tanker n'avait pas de ı sans point et Outfit n'avait ni ş, ni ğ, ni İ, donc ces lettres retombaient sur une autre police dans les titres. Télécharge le woff2 de chaque graisse séparément avec site_fetch dans `assets/fonts/`, écris les règles @font-face avec `font-display: swap` dans `assets/app.css` (design-check y cherche la police personnalisée) et vérifie le nom de font-family dans le CSS téléchargé. Précharge les polices de titre et de texte utilisées au-dessus de la ligne de flottaison sur chaque page avec `<link rel="preload" as="font" type="font/woff2" crossorigin>`, avant la feuille de style ; ne précharge pas plus de deux fichiers, car précharger une troisième graisse dans la démo a rallongé le LCP mobile de 0,2 seconde. La plupart des polices Fontshare n'ont pas le signe ₺, écris donc "TL" pour les prix.
4. Rends le menu et le pied de page statiques en HTML. Ne charge pas chrome.js ni site.config.js sur les pages. Écris un petit `chrome-stamp.mjs` qui lit la liste de navigation dans site.config.js et estampille `_src/header.tpl` et `_src/footer.tpl` entre les marqueurs `<!-- nav:start --><!-- nav:end -->` et `<!-- footer:start --><!-- footer:end -->` sur chaque page, en ajoutant aria-current="page" au lien actif. Les templates ne doivent pas se terminer par .html et doivent utiliser des placeholders comme `[[NAV]]` plutôt que `{{...}}`. Construis le menu mobile sans JS avec `<details>`. Garde le nom de l'organisation, l'adresse et le téléphone en texte brut dans le pied de page, et donne à chaque cible tactile au moins 44x44 px, liens du pied de page et du fil d'Ariane compris.
5. Convertis les images pendant leur téléchargement avec site_fetch : écris la même photo avec resize="480x", "800x" et "1200x", image_format="webp", quality=65 dans des fichiers séparés. site_fetch ne recadre jamais ; quand une photo Unsplash a besoin d'un autre ratio, télécharge la version recadrée en ajoutant des paramètres comme `?w=1600&h=1200&fit=crop` à son URL. Donne à chaque `<img>` srcset, sizes ainsi que width et height correspondant au vrai ratio. L'image principale au-dessus de la ligne de flottaison reçoit fetchpriority="high" et n'est pas lazy ; les autres reçoivent loading="lazy" decoding="async". Si l'image principale remplit l'écran sur mobile, sers un recadrage plus petit avec `<picture>`.
6. Écris la version SVG du logo en favicon.svg avec site_write_file et ajoute `<link rel="icon" href="/favicon.svg" type="image/svg+xml">` à chaque page. Sans favicon, le navigateur journalise une 404 et Best Practices tombe à 96.
7. Règles du validateur HTML : commence par un `<!DOCTYPE html>` en majuscules, utilise ` ` pour les espaces dans le texte visible des liens tel:, n'utilise jamais d'attribut style="", donne type="button" à chaque bouton, et ne mets pas de `<details>` dans une `<figure>` après sa figcaption.
8. Télécharge les bibliothèques d'animation (GSAP, ScrollTrigger) depuis jsdelivr dans `assets/vendor/` avec site_fetch, fixe la version et ne les charge que sur la page du rapport. N'utilise pas `<script defer>` ; place un petit chargeur en fin de page qui attend l'événement load, deux appels à requestAnimationFrame puis requestIdleCallback, et ajoute les scripts dans l'ordre avec async=false. Un script d'une ligne dans `<head>` ajoute la classe `js` à `<html>` et la classe `anim` sauf si prefers-reduced-motion vaut "reduce" ; sans `anim`, le chargeur ne télécharge rien. Définis les états de départ masqués uniquement sous `.anim`, et ajoute une animation CSS de secours qui révèle tous les éléments masqués après 2,5 secondes au cas où la bibliothèque n'arriverait jamais. Dans les démos précédentes, les bibliothèques en defer poussaient le LCP mobile à 3,2 secondes ; avec ce chargeur, les pages ont mesuré entre 99 et 100. Nomme l'attribut des éléments révélés au scroll data-reveal ; design-check ne reconnait l'animation que sous ce nom.
SEO, AEO et GEO :
1. Utilise des URL de type répertoire avec une barre oblique finale (/yontem/, /dernek/, /gizlilik/). Remplis le bloc seo de site.config.js et exécute `node seo-stamp.mjs`. Écris le schema propre à chaque page (page du rapport : WebPage avec un Report comme mainEntity, incluant headline, datePublished, dateModified, image, author (Person, l'éditeur) et publisher, plus FAQPage ; méthodologie : Article ; page de l'organisation : AboutPage avec un sous-type adapté à l'organisation (par exemple NGO) ; BreadcrumbList sur les pages intérieures. S'il n'y a pas de bureau accueillant du public, mets localBusiness:false dans site.config.js) dans des blocs `<script type="application/ld+json">` séparés et relie-les au graphe de base par @id. N'imbrique pas BreadcrumbList dans @graph ; garde-le dans son propre bloc, car c'est la seule façon pour seo-check de le voir.
2. Garde les titres à 60 caractères maximum (seo-check signale comme erreur tout ce qui dépasse 65), les descriptions entre 120 et 158 caractères, un seul h1 par page et aucun niveau de titre sauté (un h3 juste après le h1 a fait tomber l'accessibilité à 98). Chaque page a besoin d'au moins 150 mots de contenu principal ; les pages contact et confidentialité ont tendance à rester en dessous.
3. Le premier paragraphe de chaque page répond directement à la question de la page. Rédige des FAQ propres à chaque page avec `<details>` et balise-les en FAQPage. Affiche l'organisation éditrice et une date de "Dernière mise à jour" dans `<time>`.
4. Dans robots.txt, consigne et justifie ta décision pour GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, Claude-SearchBot, PerplexityBot, Perplexity-User, Google-Extended, Applebot-Extended, Bingbot et CCBot, et indique le sitemap. Donne à sitemap.xml de vraies dates lastmod. llms.txt contient un résumé exact du site en deux phrases, les faits clés et une liste des pages importantes.
5. Aucune invention : n'écris ni avis, ni notes, ni récompenses, ni nombres de clients, ni certificats, ni horaires d'ouverture, ni coordonnées, ni prix sans me demander. Laisse totalement hors du schema tout champ que tu ne connais pas.
Contrôles (dans l'ordre ; ne dis pas « terminé » avant qu'ils soient tous passés) :
1. Avec site_run_command, exécute `node chrome-stamp.mjs`, le build Tailwind, `node seo-stamp.mjs`, `node seo-check.mjs` (0 erreur, 0 avertissement), `node design-check.mjs` (0 erreur ; justifie tout avertissement restant) et `npx html-validate "**/*.html"` (0 erreur).
2. Affiche chaque page avec site_preview en view="mobile" et view="desktop". site_preview capture la page avec l'animation désactivée (reduced-motion) ; si du contenu manque dans cette capture, l'état sans animation est cassé. Les images lazy plus bas peuvent être vides dans la capture pleine page ; ne le compte pas comme une erreur, mais vérifie leurs chemins.
3. Lance core_web_vitals avec strategy="mobile" et strategy="desktop" pour chaque page. Critères d'acceptation : sur mobile, Performance d'au moins 95 et Accessibility, Best Practices et SEO à 100 ; sur desktop, les quatre à au moins 95. Pour une page qui échoue, trouve le fichier lent avec resources=true, corrige-le et mesure à nouveau. Lance ensuite seo_audit sur la page d'accueil avec strategy="mobile" et runs=2. Aucune adresse extérieure à votre propre domaine ne doit rester dans la liste des requêtes réseau.
4. Pas de défilement horizontal à 360, 390, 768 et 1440 px, cibles tactiles d'au moins 44 px et aucune erreur dans la console. Le site doit aussi être impeccable dans un cadre de 390x790 et de 1440x898, comme sur les pages de prompts.
Contrôle de l'animation : site_preview ne peut pas montrer l'animation, alors dis-moi ce qu'il faut observer dans mon propre navigateur. Sur ordinateur, les compteurs doivent compter de zéro jusqu'à la valeur finale en entrant dans la vue, les lignes des graphiques doivent se dessiner de gauche à droite au défilement avec les points qui apparaissent tour à tour, et la liste de chapitres à gauche doit signaler le chapitre en cours de lecture. Sur mobile, la bande de chapitres doit rester collée en haut et faire glisser le chapitre actif dans la vue. Avec la réduction des animations activée et avec JavaScript désactivé, chaque chiffre affiche sa valeur finale et chaque graphique est entièrement tracé ; les tableaux de données peuvent être ouverts.
Après la publication : prévisualise la règle `/assets/* Cache-Control: public, max-age=31536000, immutable` avec site_headers et applique-la après mon accord ; à partir de là, versionne le nom du fichier à chaque modification du CSS ou du JS (site-v2.css, etc.). Soumets sitemap.xml avec gsc_submit_sitemap et vérifie la page d'accueil avec gsc_url_inspect. Pour finir, donne-moi : un tableau des scores par page (page, quatre scores mobile, quatre scores desktop, LCP, CLS), les résultats des contrôles, le résultat des interactions testées dans un navigateur et la liste des correctifs appliqués.