À compléter avant l'envoi
[brand name][server name][what it makes, where, for whom][name][measurements, or "none"][workshop or shop address, WhatsApp number, store link if any][if any][email][phone][address][domain][links]
Crée un site multipage de mode ou de lifestyle, façon lookbook, avec des transitions d'image entre les pages, pour [brand name] sur le site [server name] de mon serveur d'hébergement Opus Growth. Marque : [what it makes, where, for whom]. Nom de la saison ou de la collection : [name]. Produits : [for each one name, category, colour, material, price and photo link]. Guide des tailles : [measurements, or "none"]. Comment on achète : [workshop or shop address, WhatsApp number, store link if any]. Livraison et retours : [if any]. Contact : [email], [phone], [address]. Domaine : [domain]. Photos du lookbook : [links].
Pages : accueil du lookbook (/), collection (/koleksiyon/), une page distincte par produit (/urun/[product-name]/), atelier ou à propos (/atolye/), contact (/iletisim/) et 404.html. Sections de l'accueil : hero (h1, courte présentation de la marque, deux boutons et une grande photo principale en hauteur), en dessous un lookbook de trois photos où chaque photo renvoie vers un produit, l'histoire de la matière ou de la fabrication, et FAQ. Page collection : filtres par catégorie et grille de produits. Page produit : grande image, nom, prix, un premier paragraphe qui dit ce qu'est le produit, une liste matière, couleur, tailles et entretien, un encadré « Comment acheter ? », le guide des tailles et deux produits de la même collection. Pas de panier ni de paiement en ligne ; l'achat se fait par WhatsApp, en boutique ou à l'atelier, et chaque page produit le dit clairement.
Style : mode éditoriale, comme un lookbook imprimé. Fond couleur tissu, photos pleine largeur aux angles droits, filets de 1 pixel, petits libellés en capitales espacées et beaucoup d'espace blanc. Typographie : une serif de mode à fort contraste de Fontshare (par exemple Melodrama 400 et 600) avec une grotesque calme pour le texte (par exemple Archivo 400 et 500). Une seule couleur d'accent (par exemple argile), uniquement pour les anneaux de focus et le survol. Dispose le trio du lookbook sur 5, 4 et 3 colonnes d'une grille de 12 colonnes, avec un décalage vertical en quinconce. Il y a deux éléments signature : la transition d'image entre les pages et l'aperçu rapide Flip dans la grille de la collection. Lenis, Swiper, ScrollTrigger et SplitText ne sont pas chargés.
Règles de transition de page et de Flip (à suivre à la lettre) :
1. View Transitions inter-documents : écris `@view-transition { navigation: auto; }` dans `assets/app.css`. L'image de la carte dans la collection et l'image principale de la page produit portent le MÊME view-transition-name ; définis-le avec une classe Tailwind à propriété arbitraire (`[view-transition-name:u-product-name]`), pas avec style="". Chaque nom ne doit apparaitre qu'une seule fois par page, car le navigateur annule la transition quand deux éléments partagent un nom ; les cartes « même collection » d'une page produit peuvent porter le nom de leur propre produit. Donne au menu du haut `view-transition-name: site-header` pour qu'il reste immobile pendant la transition. Durée du groupe : 0,5 seconde, fondu enchainé de la racine : 0,3 seconde. Dans `@media (prefers-reduced-motion: reduce)`, écris `@view-transition { navigation: none; }`. Les navigateurs sans prise en charge naviguent simplement de façon normale ; n'écris aucun repli JavaScript.
2. Charge GSAP et Flip uniquement sur la page collection ; aucune autre page n'a de script. Télécharge le cœur de GSAP 3.13 et le plugin Flip depuis jsdelivr dans `assets/vendor/` avec site_fetch et fige la version. Un script d'une ligne dans `<head>` ajoute la classe `js` à `<html>`, ainsi que la classe `anim` sauf si prefers-reduced-motion vaut « reduce ». Un petit chargeur en fin de page attend l'événement load, deux appels à requestAnimationFrame et requestIdleCallback, ne télécharge rien si `anim` est absent, et sinon ajoute dans l'ordre gsap.min.js, Flip.min.js et un minuscule fichier contenant `gsap.registerPlugin(Flip)` avec async=false.
3. Sépare l'interaction de Flip : `assets/koleksiyon.js` (defer) exécute le filtre et l'aperçu rapide AUSSI SANS Flip. À chaque changement, si Flip et `anim` sont présents, prends d'abord `Flip.getState(cards)`, modifie le DOM, puis appelle `Flip.from(state, {duration: 0.6, ease: "power3.inOut", nested: true})` ; sinon applique le changement instantanément. Ainsi, un visiteur qui ne veut pas d'animation peut quand même utiliser le filtre et l'aperçu rapide.
4. Filtre : les boutons « Tout » et ceux des catégories se trouvent dans un conteneur avec `role="group"` et un aria-label, chacun avec `aria-pressed`. Les cartes qui ne correspondent pas reçoivent `hidden` ; dans Flip, utilise `absolute: true`, onEnter pour les cartes qui entrent (opacité et échelle de 0,92 à 1) et onLeave pour celles qui sortent. Un élément `aria-live="polite"` annonce le résultat, par exemple « 3 produits affichés ».
5. Aperçu rapide (morphing de la grille vers le détail) : chaque carte a un bouton « Aperçu rapide » avec `aria-expanded` et `aria-controls`, et un panneau de détail `hidden` (description, conseil de style, lien vers la page produit). À l'ouverture, la carte occupe toute la largeur avec `grid-column: 1 / -1` et, sur ordinateur, se répartit en deux colonnes, image à gauche et détails à droite ; Flip anime l'image qui grandit depuis la petite vignette jusqu'à la grande vue. Mets à jour le `sizes` de l'image ouverte pour la grande vue afin qu'un fichier plus grand soit chargé. Une seule carte est ouverte à la fois, le texte du bouton devient « Fermer » et le focus passe au panneau, qui a tabindex="-1".
6. Sans JavaScript, les boutons de filtre et d'aperçu rapide sont masqués (`.js-only` ne s'affiche que sous `.js`), et chaque carte et chaque lien de page produit continuent de fonctionner. Le lien principal de la carte mène toujours à la page produit ; l'aperçu rapide est un bouton distinct.
Mise en place et pièges connus (chacun a couté des points ou fait échouer un contrôle lors de la mesure de démonstration, 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 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 de mouvement et bibliothèques qui NE seront PAS chargées) dans un court fichier 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, puis 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 dans 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 en ligne, chrome.js et motion.js, et ne lie que `/assets/site.css`. Recompile après chaque modification du HTML. Ajoute aussi `assets/koleksiyon.js` à la liste content, car il écrit des classes comme `is-open`.
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 CHAQUE graisse utilisée au-dessus de la ligne de flottaison (titre, 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 signe ₺, alors écris 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 espaces réservés comme `[[NAV]]` à la place de `{{...}}`. Construis le menu mobile avec `<details>`, sans JS. Garde le nom de l'entreprise, l'adresse et le téléphone dans le pied de page en texte brut, et fais en sorte que les liens du pied de page et du fil d'Ariane fassent au moins 44 pixels de haut.
5. Convertis les images pendant leur 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>` un srcset, un 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'au véritable élément LCP, et loading="lazy" decoding="async" aux autres.
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 enregistre un 404 pour /favicon.ico et les Bonnes pratiques tombent à 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 Tailwind à propriété arbitraire comme `[--r:-4deg]`), donne à chaque bouton type="button", ne mets pas d'aria-label sur des éléments sans rôle comme `<ul>` ou `<div>`, et utilise `<section aria-label="...">` à la place de role="region".
8. Télécharge les images produit avec site_fetch au ratio portrait 4:5 avec resize="400x", "640x" et "960x" ; garde toutes les photos produit au même ratio pour que la grille reste régulière et que la transition Flip ne saute pas. L'image principale d'une page produit est l'élément LCP de cette page et reçoit fetchpriority="high".
9. Vérifie les chiffres de la police d'affichage : dans la démo, le zéro de Melodrama était barré et « 2026 » dans le h1 se lisait comme « 2Ø26 » de loin. Évite les chiffres dans les titres en police d'affichage, ou compose les chiffres avec la police du texte.
SEO, AEO et GEO :
1. Utilise des URL de type répertoire avec une barre oblique finale (/koleksiyon/, /urun/[product-name]/, /atolye/, /iletisim/ ou leurs équivalents dans votre langue). Remplis le bloc seo de site.config.js et exécute `node seo-stamp.mjs`. S'il existe un atelier ou une boutique physique, définis le businessType le plus précis dans site.config.js (par exemple ClothingStore) et l'adresse ; n'ajoute les horaires d'ouverture que si je te les donne. Schémas par page : accueil WebPage et FAQPage ; collection CollectionPage et un ItemList de toutes les url de produits ; chaque page produit ItemPage et Product (name, description, image, sku, color, material, category, brand et une Offer avec price, priceCurrency TRY, availability, itemCondition, url et seller @id) ; atelier AboutPage ; contact ContactPage ; BreadcrumbList sur les pages intérieures (Lookbook, Collection, produit). Même sans paiement en ligne, l'Offer porte le bon prix et l'état du stock ; si je fournis des conditions de livraison et de retour, ajoute shippingDetails et hasMerchantReturnPolicy à l'Offer. N'invente ni avis ni notes (aggregateRating). É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 considère 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 atelier et contact sont arrivées à 113 et 95 mots du premier coup et ont été complétées avec de vraies informations, comme « ce que nous faisons à l'atelier » et « ce qu'il faut préciser quand vous écrivez ». Sur les pages produit, écris les phrases communes (entretien, tissu) sous forme de courts éléments de liste et rédige la description séparément pour chaque produit ; seo-check signale du contenu dupliqué quand des pages partagent plus de 50 pour cent de leurs phrases.
3. Le premier paragraphe de chaque page répond directement à la question de la page, et le h1 est formulé comme cette question. Écris 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 raison 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. Tout champ que tu ne connais pas est laissé entièrement hors du schéma.
Contrôles (dans l'ordre ; ne dis pas « terminé » avant que tous soient validé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 le compte pas 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 Accessibilité, Bonnes pratiques et SEO à 100 ; sur ordinateur, les quatre scores à au moins 95, objectif 100. Pour une page qui échoue, repère 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 vers la 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 dans la console.
Contrôle des interactions : comme site_preview ne peut pas montrer le mouvement, dis-moi ce qu'il faut observer dans mon propre navigateur : dans Chrome ou Edge, un clic sur un produit de la collection fait grandir l'image depuis sa carte jusqu'à sa place sur la page produit pendant que le menu reste en place ; dans Firefox, la page s'ouvre simplement ; appuyer sur un filtre fait glisser les cartes vers leur nouvel ordre ; « Aperçu rapide » ouvre la carte dans la grille et l'image grandit ; avec la réduction des animations activée, les mêmes actions se produisent instantanément ; avec JavaScript désactivé, tous les produits restent visibles. Lors d'un test local, j'ai aussi vu `document.documentElement.matches(':active-view-transition')` renvoyer true sur la page produit pendant la transition ; tu peux lancer le même test.
Après la publication : prévisualise avec site_headers la règle `/assets/* Cache-Control: public, max-age=31536000, immutable` et applique-la une fois que j'ai validé ; à 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. À la fin, donne-moi : un tableau des scores par page (page, quatre scores mobile, quatre scores ordinateur, LCP, CLS), les résultats des contrôles et la liste des corrections appliquées.