À compléter avant l'envoi
[brand name][server name][product name, what it does, for whom][price][your own other models and their figures][store URL and variant parameter][periods and terms][email][phone][WhatsApp number][address][domain]
Construis une page produit direct-to-consumer et quelques pages complémentaires pour [brand name], ma marque mono-produit, sur le site [server name] de mon serveur d'hébergement Opus Growth. Produit : [product name, what it does, for whom]. Prix : [price]. Couleurs ou variantes : [for each one a name, colour code and a photo link shot from the SAME angle on the SAME canvas]. Caractéristiques : [dimensions, material, weight and performance figures with their test conditions]. Modèles à comparer : [your own other models and their figures]. Lien d'achat : [store URL and variant parameter]. Livraison, retours et garantie : [periods and terms]. Contact : [email], [phone], [WhatsApp number], [address]. Domaine : [domain].
Pages : accueil produit (/), garantie et retours (/garanti-ve-iade/), contact (/iletisim/), confidentialité (/gizlilik/) et 404.html. Sections de l'accueil dans l'ordre : hero (vitrine 3D à gauche ; à droite, label, h1, introduction en deux phrases, prix, sélecteur de couleur, bouton d'achat et un résumé livraison, retours et garantie), trois courtes sections sur le fonctionnement du produit, un tableau des caractéristiques (#ozellikler), un tableau de comparaison des tailles ou des modèles (#karsilastir), FAQ (#sss). Le menu pointe vers ces sections de la page, ainsi que vers les pages garantie et contact. Ce site n'a ni panier ni paiement ; le bouton d'achat renvoie vers la page de la boutique avec la variante sélectionnée, et la page l'indique clairement.
Style : une page produit direct-to-consumer propre et moderne. Un fond blanc cassé chaud, une seule couleur de marque assortie au produit, un bouton d'achat noir arrondi et des tableaux épurés. Typographie : une grotesque display serrée de Fontshare (par exemple Familjen Grotesk 500 et 700) avec une police de texte lisible (par exemple Ranade 400 et 500). La photo du produit est la vedette ; garde l'audace pour la vitrine 3D. GSAP, Lenis et Swiper ne sont pas chargés ; le seul JavaScript est un script inline de moins de 1 Ko qui incline la vitrine.
Règles de la vitrine 3D, du sélecteur de couleur et de la barre d'achat (à suivre à la lettre) :
1. Construis la vitrine 3D en CSS : `perspective: 1100px` sur le conteneur, `transform: rotateX(var(--rx, 3deg)) rotateY(var(--ry, -7deg))` et `transform-style: preserve-3d` sur la carte interne, et une transition de transform de 0,3 seconde. Sans JavaScript et sur les écrans tactiles, la carte reste dans cette pose légèrement inclinée. Deux petits badges (par exemple la capacité et un chiffre de performance) flottent devant la carte avec `translateZ(60px)` et sont en aria-hidden ; la même information figure aussi dans le texte. Place sur l'image un reflet doux qui suit le pointeur (un radial-gradient piloté par --gx et --gy).
2. Le script d'inclinaison est inline en fin de page et ne s'exécute que si `matchMedia("(pointer: fine) and (prefers-reduced-motion: no-preference)")` correspond. Sur pointermove, il convertit la position du pointeur dans la carte en une valeur de -0,5 à 0,5, règle --ry à 8 degrés au maximum et --rx à 6 degrés au maximum, et limite les écritures avec requestAnimationFrame ; sur pointerleave, il supprime les variables et revient à la pose par défaut. Seul transform change, la mise en page ne bouge jamais. Ajoute un attribut data-reveal="tilt" au conteneur de la vitrine pour que design-check reconnaisse l'animation.
3. Construis le sélecteur de couleur sans JavaScript : dans un `<fieldset>` et `<legend>`, un vrai `<input type="radio" name="colour">` par variante, enveloppé dans un `<label>` de 44x44 pixels ; le radio est masqué visuellement (sr-only), la pastille de couleur reçoit un double anneau via `input:checked + .dot` et un anneau de focus via `input:focus-visible + .dot` ; les touches fléchées changent la couleur. Toutes les images de variantes sont superposées dans la même boite `aspect-ratio` avec `position: absolute; inset: 0`, et seule l'`opacity` change, de sorte que la mise en page ne se décale jamais au changement de couleur (CLS 0 dans la démo). Reflète le choix avec `.product:has(#r-colour:checked)` sur l'image, le nom de la couleur dans la legend et le lien d'achat. Si le navigateur ne gère pas :has, l'image, le nom et le lien de la variante par défaut restent visibles.
4. L'image de la variante par défaut est l'élément LCP : fetchpriority="high", pas de lazy. Les autres images de variantes reçoivent loading="lazy" decoding="async". Les photos de variantes doivent être prises sous le même angle, sur le même canevas et avec le même cadrage ; sinon le produit saute au changement de couleur. Demande-moi plutôt que d'essayer d'accorder par recadrage des photos prises sous des angles différents.
5. Ne laisse pas la valeur `display` d'une classe de bouton comme `.btn-buy` écraser la visibilité des liens d'achat des variantes. Dans la démo, la règle `.vb { display: none }` était écrasée par `.btn-buy { display: inline-flex }` plus bas, et les quatre boutons d'achat s'affichaient en même temps ; écris la règle avec un sélecteur plus spécifique comme `.product :is(.vb)` et vérifie dans le navigateur qu'un seul bouton s'affiche.
6. Barre d'achat fixe sur mobile : en dessous de 768 pixels, une barre `position: fixed; bottom: 0` avec le nom du produit et le prix, le nom de la couleur sélectionnée et un seul bouton « Acheter » (au moins 48 pixels). Garde le texte du bouton court et sur une seule ligne (`whitespace-nowrap`) ; place le nom de la couleur dans le bouton en texte sr-only pour les lecteurs d'écran. Donne au body un padding bas égal à la hauteur de la barre pour qu'elle ne recouvre jamais le contenu ni le pied de page, et vérifie que le dernier lien en bas de page reste au-dessus de la barre. La barre est masquée sur desktop.
7. Tableaux : le tableau des caractéristiques a des en-têtes de ligne `<th scope="row">`, un `<caption>` masqué visuellement et une phrase indiquant les conditions de test (par exemple température ambiante, couvercle fermé). Dans le tableau de comparaison, ne compare que tes propres modèles, sans nom de concurrent ni allégation sur la concurrence ; mets en évidence le modèle en vente par une couleur de fond sans t'appuyer sur la couleur seule. Enveloppe le tableau dans `<section aria-label="..." tabindex="0" class="overflow-x-auto">` pour qu'il ne déborde jamais sur les écrans étroits ; n'écris pas role="region", que html-validate signale comme prefer-native-element.
Mise en place et pièges connus (chacun a couté des points ou fait échouer un contrôle lors de la mesure de la démo, ne les saute pas) :
1. Si un site est déjà en ligne sur le serveur, dis-le-moi d'abord, car l'installation écrase index.html et le dossier assets. Prévisualise d'abord scaffold_site avec confirm=false, puis appelle confirm=true une fois que j'ai validé. Lis ensuite site_design_guide et site_seo_guide. Avant d'écrire du code, rédige 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 hors 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 enchaine avec site_command_status. Les chemins content de `tailwind.config.js` doivent couvrir tous les fichiers HTML, sous-dossiers compris, les modèles `_src/*.tpl` et tout fichier JS qui écrit des classes. `_src/tw.css` contient la ligne `@import "../assets/app.css";` et les trois lignes `@tailwind` ; compile-le en un seul fichier avec `npx tailwindcss -c tailwind.config.js -i _src/tw.css -o assets/site.css --minify`. Retire des pages le script cdn.tailwindcss.com, le tailwind.config inline, chrome.js et motion.js, et ne lie que `/assets/site.css`. Recompile après chaque modification du HTML. Si tu définis les pastilles de couleur avec des classes à valeur arbitraire comme `bg-[#28385C]`, elles sont compilées parce qu'elles figurent dans le HTML.
3. Auto-héberge les polices. Lis le CSS de Fontshare avec une requête par famille et par graisse (`https://api.fontshare.com/v2/css?f[]=family@weight`), télécharge chaque fichier woff2 dans `assets/fonts/` avec site_fetch et écris les règles @font-face avec `font-display: swap` dans `assets/app.css` ; design-check y cherche la police personnalisée. Précharge TOUTES les graisses utilisées au-dessus de la ligne de flottaison (titres, texte et boutons) sur chaque page avec `<link rel="preload" as="font" type="font/woff2" crossorigin>` et place ces lignes avant le lien de la feuille de style. La plupart des polices Fontshare n'ont pas le symbole ₺, écris donc les prix avec « TL ».
4. Rends le menu et le pied de page en HTML statique. É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. Ne donne pas aux modèles l'extension .html et utilise des placeholders comme `[[NAV]]` au lieu de `{{...}}`. Construis le menu mobile avec `<details>` et sans JS. Garde le nom de l'entreprise, l'adresse et le téléphone dans le pied de page en texte brut, et donne aux liens du pied de page et du fil d'Ariane une hauteur d'au moins 44 pixels.
5. Convertis les images pendant le téléchargement avec site_fetch : écris la même photo dans des fichiers séparés avec resize="480x", "800x" et "1120x" (ou les largeurs dont la page a besoin), image_format="webp" et quality=65. Donne à chaque `<img>` srcset, sizes ainsi qu'une width et une height correspondant au vrai ratio. L'image principale au-dessus de la ligne de flottaison reçoit fetchpriority="high" et n'est pas lazy ; ne donne fetchpriority qu'à l'élément LCP réel, et loading="lazy" decoding="async" au reste. Télécharge les images de variantes en 4:5 avec resize="480x", "720x" et "960x".
6. Écris un petit `favicon.svg` à la racine du site et ajoute `<link rel="icon" href="/favicon.svg" type="image/svg+xml">` à chaque page ; s'il existe un logo PNG, crée une apple-touch-icon avec site_fetch, resize="180x180" et image_format="png". Sans favicon, le navigateur journalise une 404 pour /favicon.ico et Best Practices tombe à 96.
7. Règles du validateur HTML : commence chaque document par un `<!DOCTYPE html>` en majuscules, mets les attributs entre guillemets doubles, utilise ` ` pour les espaces dans le texte visible des liens tel:, n'utilise jamais d'attribut style="" (si tu as besoin d'une variable CSS, utilise une classe de propriété arbitraire Tailwind comme `[--r:-4deg]`), donne à chaque bouton type="button", ne mets pas aria-label sur des éléments sans rôle comme `<ul>` ou `<div>`, et utilise `<section aria-label="...">` au lieu de role="region".
8. Un audit des zones tactiles peut signaler le radio masqué visuellement comme faisant 1 pixel ; la vraie zone tactile est le label qui l'entoure. Mesure que le label fait au moins 44x44 pixels et note la raison dans le rapport.
SEO, AEO et GEO :
1. Utilise des URL en style répertoire avec une barre oblique finale (/garanti-ve-iade/, /iletisim/, /gizlilik/ ou leurs équivalents dans ta langue). Remplis le bloc seo de site.config.js et exécute `node seo-stamp.mjs`. Pour une marque sans boutique physique, mets localBusiness:false dans site.config.js. Page d'accueil : ItemPage (mainEntity le produit), le schéma produit et FAQPage. Schéma produit : avec une seule variante, Product et Offer ; avec des variantes de couleur, un ProductGroup (productGroupID, variesBy https://schema.org/color, brand, description, material) et, dans hasVariant, un Product par couleur (sku, color, image) avec une Offer (price, priceCurrency TRY, availability, itemCondition, l'URL boutique de la variante comme url, seller @id, shippingDetails avec OfferShippingDetails et hasMerchantReturnPolicy avec MerchantReturnPolicy). Publie la même MerchantReturnPolicy avec son @id dans son propre bloc sur la page garantie et retours. N'ajoute GTIN, notes ou avis que si j'ai de vraies valeurs. Écris chaque schéma propre à une page dans son propre bloc `<script type="application/ld+json">` et relie-le au graphe de base avec @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. Titres de 48 à 60 caractères (seo-check traite plus de 65 comme une erreur), descriptions de 145 à 158 caractères, un seul h1 par page. Le contenu principal de chaque page fait au moins 150 mots. Dans la démo, les pages garantie et retours, confidentialité et contact sont arrivées à 141, 124 et 106 mots du premier coup et ont été complétées avec de vraies informations comme « démarches de retour », « avec qui les données sont partagées » et « ce qu'exige une demande de garantie ».
3. Le premier paragraphe de chaque page répond directement à la question de la page, et le h1 est formulé comme cette question. Rédige la FAQ propre à la page avec `<details>` et balise-la en FAQPage. Affiche l'organisation éditrice et une mention « Dernière mise à jour » avec `<time datetime>`.
4. Dans robots.txt, écris ta décision avec sa justification 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. sitemap.xml a un vrai lastmod. llms.txt contient un résumé exact du site en deux phrases et la liste des pages importantes.
5. Pas d'invention : n'écris ni avis, ni notes, ni récompenses, ni nombre de clients, ni certificats, ni horaires d'ouverture, ni coordonnées, ni prix, ni chiffres produit sans me demander. Laisse tout champ que tu ne connais pas entièrement en dehors du schéma.
Contrôles (dans l'ordre ; ne dis pas « terminé » avant que tous soient passés) :
1. Avec site_run_command, exécute dans l'ordre `node chrome-stamp.mjs`, la compilation 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, view="mobile" et view="desktop". site_preview capture la page avec les animations désactivées ; si le contenu n'est pas complet dans cette capture, l'état sans animation est cassé. Les images lazy plus bas peuvent être vides dans une capture pleine page ; ne compte pas cela comme une erreur, mais vérifie leurs chemins.
3. Lance core_web_vitals pour chaque page avec strategy="mobile" et strategy="desktop". Critères d'acceptation : sur mobile, Performance d'au moins 95 et Accessibility, Best Practices et SEO à 100 ; sur desktop, les quatre d'au moins 95, objectif 100. 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. La liste des requêtes réseau ne doit contenir aucune adresse extérieure à ton propre domaine (les liens boutique et WhatsApp sont des liens, pas des requêtes).
4. Aucun défilement horizontal à 360, 390, 768 et 1440 pixels de large, zones tactiles d'au moins 44 pixels, aucune erreur console.
Vérification des interactions : comme site_preview ne peut montrer ni animations ni clics, dis-moi ce qu'il faut observer dans mon propre navigateur : sur desktop, déplacer la souris sur le produit incline la carte vers le pointeur avec les badges flottant devant, et elle revient à la pose inclinée quand la souris sort ; cliquer sur une pastille de couleur ou appuyer sur une touche fléchée change l'image, le nom de la couleur et le lien d'achat sans que rien ne bouge sur la page ; avec JavaScript désactivé, le sélecteur de couleur fonctionne toujours ; sur téléphone, la barre du bas est toujours visible et ne recouvre pas les liens de fin de page ; avec la réduction des animations activée, la carte ne s'incline pas.
Après la publication : prévisualise la règle `/assets/* Cache-Control: public, max-age=31536000, immutable` avec site_headers et applique-la une fois que j'ai validé ; à partir de là, versionne le nom de 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. À la fin, donne-moi : un tableau des scores par page (page, quatre scores mobile, quatre scores desktop, LCP, CLS), les résultats des contrôles et la liste des correctifs appliqués.