forked from ORGANISATION-KA-INTERNATIONALE/FEDIVERSE-OKI
d6efb6736f
- DonnĂ©es PeerTube (GADE), Castopod (KUTE) et Mastodon (BOKANTE) bakĂ©es au build via +page.server.ts (throttle + retry 429 + dĂ©duplication) - Charte OKI complĂšte : tokens, thĂšme sombre par dĂ©faut (clair opt-in, anti-FOUC), Archivo/Inter self-hĂ©bergĂ©es, flag-bar, sprite SVG (zĂ©ro emoji en interface, zĂ©ro Font Awesome/CDN) - i18n FR/EN par routage [[locale]], bundles JSON, hreflang, %lang% serveur - Pages : accueil, /video/[uuid] (embed, tĂ©lĂ©chargements, partage, commentaires, JSON-LD VideoObject), /categories/[id], /recherche (index JSON bakĂ©, recherche client), /direct (live + annonce multi-fuseaux), /dons, /mentions-legales, /offline + 404 krĂ©yĂČl - Motion gwoka : KineticText (scrub view()), ScrollProgressBar, FlagChip, reveal syncopĂ©, View Transitions, gate prefers-reduced-motion unique - PWA : manifest + Workbox generateSW (fallback /offline/), registerSW statique - SĂ©curitĂ© : CSP par page en <meta> (SHA-256 des inline via scripts/postbuild-csp.mjs) + headers globaux (_headers Cloudflare et .htaccess o2switch), redirections des anciennes URLs PHP - Doc : docs/DEPLOIEMENT-SVELTEKIT.md
495 lines
41 KiB
Markdown
495 lines
41 KiB
Markdown
# PLAYBOOK UNIFIĂ â OKI Ă SVELTEKIT
|
||
### Document de rĂ©fĂ©rence opĂ©rationnel pour agent de code â marque OKI, mĂ©thode Awwwards-grade, conventions Svelte 5, briques rĂ©utilisables
|
||
|
||
> **Nature :** fusion de `charte-oki-design-system.md`, `recette-sveltekit-playbook-agent.md`, `recette-sveltekit-15-sites-awwwards.md`, `svelte-5_code_writer.md`, `svelte_core_bestpractices.md` et `AGENTS.md`, enrichie des leçons réelles de **6 missions** (juillet 2026) : migration o-k-i.net, refonte atlas-fediverse, finalisation exitchatcontrol, migration gwada-sirius, refonte UX/motion du jeu JWE, réparation et modernisation d'oki-podcast-reader (voir §5, §5b et §5c). Document **local, non versionné** (`.gitignore`).
|
||
>
|
||
> **Usage :** à fournir à l'agent pour toute demande du type « transforme ce projet web en projet Svelte aux couleurs OKI, style Awwwards » ou « crée un site/PWA dans cette charte ». Compléter avec le brief de mission du §7.
|
||
>
|
||
> **Priorités en cas de conflit :** la marque (§1) prime pour couleurs, typo, voix, iconographie · la méthode (§2) prime pour la technique · les budgets et l'accessibilité ne se négocient jamais.
|
||
|
||
---
|
||
|
||
## 0. TYPES DE MISSION
|
||
|
||
**A. Transformation** d'un site existant (HTML statique, WordPress, Eleventy, SPA sans DA) â SvelteKit aux couleurs OKI. Toujours commencer par l'audit (§2.4 phase 1) â le descriptif du site source est **toujours** Ă vĂ©rifier contre le dĂ©pĂŽt rĂ©el (la migration o-k-i.net partait d'un brief « HTML statique » alors que le site Ă©tait Eleventy + 38 JSON i18n).
|
||
|
||
**B. Création** d'un nouveau site/PWA dans la charte OKI. Commencer au §2.4 phase 2, en copiant les briques du §4.
|
||
|
||
**C. Finalisation** â le chantier est dĂ©jĂ avancĂ© (migration Ă 90 %, WIP non commitĂ©). Le travail est de **finir, pas recommencer** : builder d'abord, committer l'existant cohĂ©rent, puis combler les manques (typiquement SEO et rĂ©gressions du changement de gĂ©nĂ©rateur).
|
||
|
||
**D. Refonte ciblĂ©e UX/motion** â la stack est dĂ©jĂ SvelteKit. Le travail est chirurgical : remplacer les piĂšces dĂ©faillantes (fond, carte, timeline, layout) et appliquer charte + motion, sans tout réécrire.
|
||
|
||
Quatre rĂšgles transverses, apprises sur 5 projets :
|
||
1. **Contenu éditorial jamais réécrit** sans instruction explicite ; les données priment sur les suppositions (ex. KUTE = Castopod dans les JSON, pas « app PHP » comme le brief le supposait).
|
||
2. **Toujours vĂ©rifier l'existence de git en premier** (atlas-fediverse n'avait AUCUN dĂ©pĂŽt â `git init` + commit de l'existant avant toute modification, sinon travail irrĂ©versible).
|
||
3. **Charte §7 « harmoniser â tout refaire »** : si le projet a dĂ©jĂ un design system de la famille OKI (tokens panafricains, polices accessibilitĂ©), on ne rebrande pas â on applique mĂ©thode et qualitĂ© (exitchatcontrol, gwada-sirius). La charte complĂšte ne s'applique qu'aux projets sans identitĂ© propre (atlas).
|
||
4. **VĂ©rifier l'Ă©tat rĂ©el avant de scoper** : sur 5 projets, 2 Ă©taient dĂ©jĂ SvelteKit (atlas, JWE), 1 en migration Ă 90 % (exitchatcontrol), 1 Ă 80 % (gwada-sirius) â une seule vraie migration complĂšte.
|
||
|
||
---
|
||
|
||
## 1. MARQUE OKI (canonique â prime sur tout le reste)
|
||
|
||
### 1.1 Identité en une phrase
|
||
|
||
Un studio web militant caribĂ©en dont la marque est un **drapeau panafricain â noir, or, vert, rouge â posĂ© sur un fond presque noir, en capitales Archivo**. Afrofuturiste caribĂ©en : un drapeau, pas une charte corporate.
|
||
|
||
Trois conséquences non négociables :
|
||
1. **ThÚme sombre = identité par défaut** ; le clair est un opt-in (`html.light-theme`) qui assombrit les accents pour WCAG AA.
|
||
2. **L'or porte toute l'interaction** â seule couleur d'action.
|
||
3. **Angles nets partout** â aucune forme organique, aucune bulle trĂšs arrondie.
|
||
|
||
### 1.2 Tokens couleurs (mesurés sur le site réel)
|
||
|
||
```css
|
||
:root {
|
||
/* Noyau (thÚme sombre = défaut) */
|
||
--noir-oki: #0D0D0D; /* background */
|
||
--noir-profond: #1A0F1A; /* surface */
|
||
--blanc-creme: #FFF8E7; /* foreground */
|
||
--line: rgba(255,255,255,0.10); /* filets â jamais de gris plein */
|
||
--or-oki: #FDB813; /* accent : SEULE couleur d'action */
|
||
--rouge-oki: #FF1654; /* signal, ponctuation â jamais un lien/bouton */
|
||
/* Ătendue (parcimonie) */
|
||
--vert-oki: #00D66C; /* succĂšs, validation, dons mensuels */
|
||
--turquoise-caraibes: #00CED1;
|
||
--jaune-soleil: #FFD700;
|
||
--orange-flamme: #FF6B35;
|
||
--violet-nuit: #6B2D5C;
|
||
--bleu-ocean: #0077BE;
|
||
--or-clair: #FFE066; /* survol des boutons */
|
||
--gris-sombre: #2D1B2E;
|
||
/* Sémantique dérivée */
|
||
--muted: color-mix(in srgb, var(--blanc-creme) 70%, transparent);
|
||
--card-bg: rgba(255,255,255,0.03);
|
||
}
|
||
/* ThĂšme clair â opt-in, accents assombris WCAG AA */
|
||
html.light-theme {
|
||
--noir-oki: #FFF8E7; --blanc-creme: #0D0D0D;
|
||
--noir-profond: #F5F0E8; --gris-sombre: #E8DDD0;
|
||
--or-oki: #B87A00; --vert-oki: #006B3D; --rouge-oki: #A01030;
|
||
--turquoise-caraibes: #006B75; --bleu-ocean: #004B7F;
|
||
--or-clair: #D99000; --jaune-soleil: #B87A00; --orange-flamme: #C85000;
|
||
--line: rgba(0,0,0,0.12); --card-bg: rgba(0,0,0,0.03);
|
||
}
|
||
```
|
||
|
||
RĂšgles d'usage : texte secondaire = crĂšme Ă 70-85 % (`--muted`), pas de couleur dĂ©diĂ©e · filets = blanc 10 % · **Rouge = signaler · Vert = valider · Or = agir â ne jamais permuter**.
|
||
|
||
### 1.3 Typographie
|
||
|
||
```css
|
||
--font-display: 'Archivo', 'Arial Black', sans-serif; /* 600-900 : TITRES + BOUTONS */
|
||
--font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; /* 400-800 */
|
||
```
|
||
|
||
- Titres h1-h4 : Archivo, MAJUSCULES, `letter-spacing: -0.01em`.
|
||
- Boutons : Archivo 700, uppercase, `letter-spacing: 0.03em`, bordure 2 px.
|
||
- Corps : Inter, `line-height: 1.5`.
|
||
- **Self-hébergement obligatoire** : woff2 dans `static/fonts/` + `fonts.css`, `font-display: swap`, preload de la display 700. Aucun appel Google Fonts (doctrine souveraineté). Source pratique : `@fontsource/archivo` + `@fontsource/inter` (npm), copier les `*-latin-*-normal.woff2`.
|
||
|
||
### 1.4 Formes, espacements, layout
|
||
|
||
```css
|
||
--radius-sm: 3px; --radius-md: 6px; /* jamais plus */
|
||
--border-card: 1px solid var(--line);
|
||
--border-btn: 2px solid var(--or-oki);
|
||
--space-1: .75rem; --space-2: 1rem; --space-3: 1.5rem; --space-4: 2rem; --space-5: 4rem;
|
||
--container: 1200px;
|
||
```
|
||
|
||
- Sections : `padding: var(--space-5) 0` · Grilles : `repeat(auto-fit, minmax(300px, 1fr))`.
|
||
- **Carte canonique** : fond `--card-bg`, liseré gauche 4 px d'accent, survol `translateY(-2px à -4px)` + bordure d'accent.
|
||
- **Tag canonique** : fond or 8 % + bordure or 1 px, rayon 3 px.
|
||
- **Bouton canonique** : balayage or `::after scaleX(0â1)` origin left au hover, `--ease-syncope`.
|
||
|
||
### 1.5 Flag-bar â signature n°1
|
||
|
||
Bandeau **6 px, 4 segments francs** : noir 0-25 % · or 25-50 % · vert 50-75 % · rouge 75-100 %. ArrĂȘts nets, **jamais de dĂ©gradĂ© entre segments**.
|
||
|
||
```css
|
||
.flag-bar { height: 6px; background: linear-gradient(to right,
|
||
#0D0D0D 0 25%, var(--or-oki) 25% 50%, var(--vert-oki) 50% 75%, var(--rouge-oki) 75% 100%); }
|
||
```
|
||
|
||
Placement : bord infĂ©rieur de la nav fixe + haut du footer. **Une occurrence pleine largeur visible par Ă©cran max.** Pour ponctuer ailleurs (titres de section, loader), utiliser le **flag chip** : mĂȘme 4 segments, 56 Ă 6 px (voir §4). En thĂšme clair, le segment noir devient `#000` pur.
|
||
|
||
### 1.6 Logotype
|
||
|
||
Monogramme « OKI » : arche or, point vert, accent rouge sur noir. Fichier canonique 512Ă512 transparent (aussi og:image, apple-touch-icon, maskable PWA). Ne jamais utiliser un logo de partenaire comme logo OKI.
|
||
|
||
### 1.7 Motion â les cadences gwoka
|
||
|
||
```css
|
||
--ease-ka: cubic-bezier(0.22, 1, 0.36, 1); /* temps fort : attaque franche, longue tenue */
|
||
--ease-syncope: cubic-bezier(0.65, 0, 0.35, 1); /* contretemps : symétrique, urgent */
|
||
--dur-tanbou: 120ms; /* double-croche â micro-interactions, hovers */
|
||
--dur-mesure: 480ms; /* une mesure â entrĂ©es de section */
|
||
--dur-phrase: 960ms; /* deux mesures â transitions de page, moments solennels */
|
||
```
|
||
|
||
1. **Le stagger de marque est syncopé (3+3+2)** : délais `[0, 120, 300, 360, 600, 660, 900, 960]` ms pour 8 éléments (puis cycles de +1200 ms). Le rythme est une identité, pas un effet.
|
||
2. Uniquement `transform` + `opacity` (+ `clip-path` pour les masques).
|
||
3. **Gate unique `prefers-reduced-motion`** au niveau global, contenu statique complet sans JS ni motion.
|
||
4. Durées toujours lues depuis les tokens, jamais hardcodées.
|
||
|
||
### 1.8 Iconographie â zĂ©ro emoji en production
|
||
|
||
Set SVG OKI : viewBox 24Ă24, **stroke 2 px**, angles nets, `currentColor` (or par dĂ©faut), remplissage rĂ©servĂ© aux †16 px, **noms krĂ©yĂČl**. LivrĂ© en `<symbol>` dans un sprite `icons.svg` + `<svg class="icon"><use href="/icons.svg#ID"/></svg>`.
|
||
|
||
Set de rĂ©fĂ©rence (existant dans o-k-i.net) : `ka` (tambour, icĂŽne maĂźtresse, 404/loader) · `lambi` (conque â annonces) · `zetwal` (Ă©toile 4 branches â navigation, instances) · `mawon` (brisure de chaĂźne â souverainetĂ©) · `lakanmou` (flamme â engagement, dons) · `jaden` (pousse â solidaritĂ©, projets) · `kannen` (canne â patrimoine, institutions) · `lanme` (vague â international) · `glo` (poing â luttes, tarifs solidaires) · `kle` (cadenas ouvert â libertĂ©, open-source) · `pawol` (bulle angulaire â langues, traduction) · `mizik-note` (note â musique).
|
||
|
||
**Pattern contenu** : si des emojis vivent dans les textes (JSON), utiliser un helper `splitLeadingEmoji()` qui convertit l'emoji décoratif en picto du sprite sans toucher au texte (implémenté dans o-k-i.net `sections/pictos.ts`).
|
||
|
||
### 1.9 Voix & ton
|
||
|
||
Vouvoiement direct et empathique, phrases courtes. La cause du visiteur d'abord, l'outil ensuite. **Ă dire :** sur mesure · tarifs adaptĂ©s Ă vos moyens · organisations engagĂ©es · transition numĂ©rique · Ă©cosystĂšme numĂ©rique libre. **Ă Ă©viter :** « template gĂ©nĂ©rique », « clĂ© en main », jargon corporate, startup-speak. Piliers : ORGANISATION KA · INTERNATIONALE · Des solutions pour chaque besoin · Le budget ne doit jamais ĂȘtre un frein. **Langues :** FR par dĂ©faut ; KA (krĂ©yĂČl) en signature et microcopy (404, loader, remerciements â attribut `lang="gcf"`) ; EN en version dĂ©diĂ©e.
|
||
|
||
### 1.10 Imagerie
|
||
|
||
Illustration afrofuturiste caribéenne : couleurs chaudes saturées sur fonds sombres. Jamais de stock corporate, jamais d'illustration startup générique. AVIF/WebP self-hébergés, `loading="lazy"` hors LCP.
|
||
|
||
### 1.11 ĂcosystĂšme
|
||
|
||
- Nom KA + logiciel en sous-titre (« BOKANTE â Mastodon ») : la transparence est un pilier.
|
||
- Footer fédéré sur tous les sous-domaines : `[monogramme] Un service libre opéré par ORGANISATION KA INTERNATIONALE · o-k-i.net` + flag-bar 6 px au-dessus.
|
||
- Favicon = monogramme partout. `*.o-k-i.net` = outils/fédivers ; `pawol.nu` = projets culturels (motion plus riche autorisé).
|
||
|
||
---
|
||
|
||
## 2. MĂTHODE TECHNIQUE (la recette)
|
||
|
||
### 2.1 Les 5 principes
|
||
|
||
- **P1 â Le scroll est le moteur.** Une seule instance Lenis au layout racine, cadencĂ©e par le ticker GSAP unique. Jamais de double rAF.
|
||
- **P2 â Bake au build, pas au runtime.** Tout ce qui ne dĂ©pend pas d'une entrĂ©e live est prĂ©calculĂ© : images responsive (vite-imagetools), textures, polices.
|
||
- **P3 â DOM d'abord, WebGL seulement oĂč ça paie.** Zentry a fait du « 3D » primĂ© en pur DOM (clip-path, preserve-3d, masks). Pour l'audience OKI (mobile 4G, Mali-G52) : **DOM/SVG uniquement** par dĂ©faut.
|
||
- **P4 â Le motion se designe avant les pages** (tokens §1.7 d'abord, composants ensuite).
|
||
- **P5 â Chaque Ă©tat est un moment designĂ©** : loader, 404, vide, hors-ligne â en KA avec le tambour `ka`.
|
||
|
||
### 2.2 Interdictions absolues
|
||
|
||
- Jamais de dĂ©pendance installĂ©e sans ĂȘtre importĂ©e et utilisĂ©e (les outils d'audit â lighthouse, puppeteer â s'installent en `--no-save` ou se retirent).
|
||
- Jamais de SSR désactivé globalement pour « faire marcher » une lib client.
|
||
- Jamais animer autre chose que `transform`/`opacity`/`clip-path` en JS.
|
||
- Jamais de page dont le contenu est invisible sans JavaScript.
|
||
- Jamais de service tiers (fonts, CDN, analytics) â tout asset se self-hĂ©berge.
|
||
|
||
### 2.3 Stack cible
|
||
|
||
```
|
||
SvelteKit 2 + Svelte 5 (runes) + TypeScript strict
|
||
@sveltejs/adapter-static (prerender intégral, trailingSlash 'always')
|
||
vite-imagetools (AVIF/WebP responsive au build)
|
||
vite-plugin-pwa (generateSW â shell hors-ligne)
|
||
lenis + gsap (imports dynamiques uniquement)
|
||
@fontsource/* (polices woff2 copiées dans static/fonts/)
|
||
CSS vanilla : oki-tokens.css + base.css + styles scopĂ©s â pas de Tailwind
|
||
```
|
||
|
||
### 2.4 Workflow en 7 phases
|
||
|
||
1. **Audit** (toujours) : pages, sections, assets, liens externes, stack mesurée, bugs de production listés AVANT toute refonte, contradictions doctrine/outillage (ex. discours anti-GAFAM + Google Fonts). Rapport validé avant de coder.
|
||
2. **Tokens & thÚme** : `oki-tokens.css` (§1), thÚme sombre défaut + clair opt-in, fonts self-hébergées, anti-FOUC par script externe (CSP).
|
||
3. **Architecture** : routes, i18n, SEO, layout. `prerender = true` partout. URLs historiques conservées.
|
||
4. **Composants** : uniquement ceux pertinents pour CE site. Chacun avec cleanup et garde reduced-motion.
|
||
5. **Motion** : transitions Svelte natives · scrub via `animation-timeline: view()/scroll()` natif d'abord, fallback GSAP ScrollTrigger en import dynamique · une seule horloge (gsap.ticker â Lenis).
|
||
6. **Performance** : budgets §2.7, pipeline images, mesure sur profil mobile.
|
||
7. **Accessibilité & dégradation** : ladder §2.8, revue clavier, contenu canvas/SVG doublé en DOM.
|
||
|
||
### 2.5 Architecture de référence (éprouvée sur o-k-i.net)
|
||
|
||
```
|
||
src/
|
||
app.html # %lang% + scripts externes (theme, lang-redirect, registerSW)
|
||
hooks.server.ts # lang fr/en via transformPageChunk (replaceAll '%lang%')
|
||
app.d.ts / imagetools.d.ts
|
||
lib/
|
||
styles/oki-tokens.css # charte §1 â LE fichier de tokens partagĂ©
|
||
styles/base.css # reset, primitives (btn, card, tag, flag-bar, icon), gate reduced-motion
|
||
i18n/ # bundles JSON par locale + index.ts (getBundle, localeFromPath, alternatePath)
|
||
assets/images/ # sources pour vite-imagetools
|
||
motion/ # tokens.ts, scroll.ts (Lenis), reveal.ts, tilt.ts
|
||
components/ # Seo, Nav, Footer, ResponsiveImage, motion/, icons/, sections/
|
||
routes/
|
||
+layout.svelte # skip-link, loader, progress, nav, footer, View Transitions, Lenis
|
||
+layout.ts # prerender = true, trailingSlash = 'always'
|
||
+error.svelte # 404/erreurs designée (KA)
|
||
offline/+page.svelte # cible navigateFallback du SW
|
||
static/
|
||
fonts/ icons.svg images/ theme.js lang-redirect.js registerSW.js
|
||
manifest.webmanifest 404.html robots.txt sitemap.xml _headers .htaccess
|
||
```
|
||
|
||
### 2.6 Composants motion (contrats)
|
||
|
||
- **KineticText** â titrage au scroll, split par **mots** (jamais caractĂšres â apostrophes), `aria-label` sur titres h1-h4 (jamais sur span : prohibĂ©), scrub `animation-timeline: view()` + fallback ScrollTrigger dynamique, stagger syncopĂ© converti en plages de scroll.
|
||
- **ScrollProgressBar** â `scaleX` via rAF + Ă©criture DOM directe (jamais d'Ă©tat rĂ©actif par frame), `role="progressbar"`.
|
||
- **PageTransition** â `onNavigate` + View Transitions API, durĂ©e lue des tokens ; fallback sobre = navigation instantanĂ©e.
|
||
- **IntroLoader** â cĂ©rĂ©monie 1re visite (`sessionStorage`), skippable, 100 % CSS pilotĂ©e par une classe posĂ©e par le script externe anti-FOUC (pas de JS inline â CSP).
|
||
- **Marquee** â bande typographique CSS pure, contenu dupliquĂ© `aria-hidden`, pause au hover, coupĂ©e en reduced-motion.
|
||
- **use:reveal** â action IO, cascade syncopĂ©e via `--d`, Ă©tat cachĂ© **uniquement** sous `html.js` + `prefers-reduced-motion: no-preference`.
|
||
- **use:tilt** â tilt 3D pointeur via variables CSS `--rx/--ry` + rAF, off tactile + reduced-motion.
|
||
- **FlagChip** â mini flag-bar 56Ă6 px qui se dessine (`scaleX`) Ă l'entrĂ©e du titre.
|
||
- **Village Ă©cosystĂšme** â scĂšne SVG isomĂ©trique des services, chaque bĂątiment = `<a>` focusable (`aria-label` « NOM â Logiciel »), hover/focus = liserĂ© or + label, fallback grille accessible (reduced-motion + mobile Ă©troit, bascule `display: none` pour Ă©viter les doubles tab stops).
|
||
- **CursorTracker, WebGL** : non retenus pour l'audience OKI (mobile-dominante).
|
||
|
||
### 2.7 Budgets (mobile 4G, Android entrée de gamme)
|
||
|
||
| Ressource | Budget | Mesuré o-k-i.net |
|
||
|---|---|---|
|
||
| JS initial compressé | †170 Ko | 69 Ko gzip (+45 Ko dynamiques) |
|
||
| Poids total accueil | †2 Mo | ~0,9 Mo |
|
||
| Média hero avant interaction | †400 Ko | ~12 Ko (logo) |
|
||
| Lighthouse mobile | â„ 90/95/95/95 | 91/100/100/100 |
|
||
| Animations JS concurrentes | †8-12, transform/opacity | OK |
|
||
| LCP / INP / CLS | < 2,5 s / < 200 ms / < 0,05 | 2,9 s / 59 ms TBT / 0,001 |
|
||
|
||
### 2.8 Accessibilité & ladder de dégradation
|
||
|
||
1. `saveData`/`effectiveType` †3g â images statiques, zĂ©ro prĂ©chargement.
|
||
2. JS dĂ©sactivĂ© â contenu SSR complet et lisible (Ă©tats cachĂ©s conditionnĂ©s Ă `html.js`).
|
||
3. `prefers-reduced-motion` â gate unique : pas de Lenis, pas de loader, pas de scrub, contenu statique complet.
|
||
4. Canvas/SVG décoratifs `aria-hidden` + miroir DOM sémantique.
|
||
5. `lang` correct à chaque bascule ; focus déplacé sur le contenu aprÚs transition de route ; skip-link ; focus visible or.
|
||
6. PiÚges éprouvés : `aria-label` interdit sur `<span>` générique · `<figcaption>` enfant direct de `<figure>` · liens dans le texte soulignés (scoper la rÚgle à `main` pour ne pas toucher nav/footer).
|
||
|
||
### 2.9 PWA légÚre
|
||
|
||
- `static/manifest.webmanifest` manuel (nom KA, monogramme any + maskable, `theme_color`/`background_color` `--noir-oki`, `display: standalone`).
|
||
- `vite-plugin-pwa` : `registerType: 'autoUpdate'`, `injectRegister: false`, `manifest: false`, workbox `navigateFallback: '/offline/index.html'`, `navigateFallbackDenylist` pour les assets binaires, `globIgnores` pour les gros fichiers (PDF), `maximumFileSizeToCacheInBytes: 3 Mo`, `cleanupOutdatedCaches`, `clientsClaim`, `skipWaiting`.
|
||
- Enregistrement par **fichier statique** `static/registerSW.js` avec chemins absolus (`navigator.serviceWorker.register('/sw.js', { scope: '/' })`), lié dans `app.html`. Ne PAS utiliser l'injection du plugin : sans `@vite-pwa/sveltekit` elle n'atteint pas le HTML pré-rendu, et le `registerSW.js` généré utilise un chemin relatif `./sw.js` cassé sur les routes imbriquées (`/en/`, `/dons/`).
|
||
|
||
### 2.10 Sécurité & CSP
|
||
|
||
CSP de référence (tout self-hébergé) :
|
||
```
|
||
default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';
|
||
img-src 'self' data:; font-src 'self'; connect-src 'self';
|
||
frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'
|
||
```
|
||
+ HSTS `max-age=31536000`, `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, `Referrer-Policy: strict-origin-when-cross-origin`, `Permissions-Policy` restrictive. Livrée en **deux formats** : `static/.htaccess` (Apache/o2switch : + `ErrorDocument 404 /404.html`, redirect HTTPS, cache immutable `/_app/` et `/fonts/`) et `static/_headers` (Cloudflare Pages). RÚgles : **aucun script inline** (snippets thÚme/langue en fichiers externes) ; `style` attributes OK (`unsafe-inline` style) ; 404 statique autonome (`static/404.html`, zéro dépendance).
|
||
|
||
### 2.11 SEO
|
||
|
||
Composant `Seo.svelte` : title/description par page, canonical, hreflang fr/en/x-default via mapping de paires d'URLs, OG Ă10 (og:image self-hĂ©bergĂ©e), Twitter Card, JSON-LD (Organization + entitĂ©s du projet). `robots.txt` + `sitemap.xml` statiques Ă jour. Astuce : les `</script>` dans les template literals `{@html}` doivent ĂȘtre Ă©chappĂ©s (`<\/script>`).
|
||
|
||
---
|
||
|
||
## 3. CONVENTIONS SVELTE 5 (obligatoires)
|
||
|
||
- **Runes only** : `$state` (uniquement pour du rĂ©actif â sinon variable plain ; gros objets rĂ©assignĂ©s : `$state.raw`), `$derived` (jamais d'`$effect` pour calculer), `$props` (traiter les props comme changeantes : valeurs dĂ©pendantes en `$derived`).
|
||
- **ĂvĂ©nements** : `onclick={...}` (jamais `on:click`) ; listeners window/document via `<svelte:window>` / `<svelte:document>`.
|
||
- **`{#each}` à clé unique** (jamais l'index).
|
||
- **CSS** : variables JS â directive `style:--var={val}` ; styles enfants via custom properties, `:global` en dernier recours ; Ă©tats globaux (`html.js`, `html.light-theme`, `html.intro-pending`) via `:global(...)`.
|
||
- **Ătats rĂ©actifs par-frame interdits** : scrollY/pointeur â variables plain + flush rAF (ou variables CSS directement).
|
||
- **Init/cleanup** : GSAP/Lenis/IO dans `onMount`/`$effect` avec cleanup symétrique (`kill()`/`revert()`/`destroy()`/`disconnect()`).
|
||
- **Liens internes** : `resolve()` / assets via `asset()` de `$app/paths` ; externes en `rel="external noopener noreferrer"` + `target="_blank"`.
|
||
- **{@html}** : uniquement sur contenu first-party (JSON du dépÎt), commenté comme tel.
|
||
- **Autofixer (AGENTS.md)** : aprĂšs tout composant modifiĂ© â
|
||
```bash
|
||
npx @sveltejs/mcp list-sections # doc Svelte 5
|
||
npx @sveltejs/mcp get-documentation "$state,$derived"
|
||
npx @sveltejs/mcp svelte-autofixer ./src/lib/MonComposant.svelte
|
||
```
|
||
(Ăchapper `\$` dans le code inline. La sortie est un objet JS, pas du JSON strict.) `npm run check` Ă **0 erreur / 0 warning** avant tout commit.
|
||
|
||
---
|
||
|
||
## 4. BRIQUES RĂUTILISABLES (rĂ©fĂ©rence : dĂ©pĂŽt o-k-i.net, branche `svelte`)
|
||
|
||
Copier et adapter, ne pas réécrire. Chaque brique a un contrat stable.
|
||
|
||
| Brique | Chemin dans o-k-i.net | Contrat / usage |
|
||
|---|---|---|
|
||
| Tokens charte | `src/lib/styles/oki-tokens.css` | importé en premier dans `+layout.svelte` |
|
||
| Primitives | `src/lib/styles/base.css` | `.btn .card .tag .icon .flag-bar .container .section`, gate reduced-motion, reveal |
|
||
| Fonts | `static/fonts/` + `fonts.css` | Archivo 600-900, Inter 400-800, woff2 latin, preload 700 |
|
||
| Anti-FOUC thĂšme | `static/theme.js` | pose `.js`, `.light-theme`, `.intro-pending` ; localStorage `oki-theme` |
|
||
| Redirection langue | `static/lang-redirect.js` | préférence `oki-lang-pref`, sinon `navigator.language` |
|
||
| i18n | `src/lib/i18n/index.ts` | bundles JSON par locale ; `getBundle(locale)`, `localeFromPath`, `alternatePath` (paires FRâEN) |
|
||
| SEO | `src/lib/components/Seo.svelte` | `<Seo title? description? path locale />` â meta + OG + Twitter + JSON-LD |
|
||
| Lang par route | `src/hooks.server.ts` | `%lang%` dans `app.html` + `transformPageChunk` |
|
||
| Lenis | `src/lib/motion/scroll.ts` | `initSmoothScroll()` (dynamic), `scrollToAnchor(hash)` |
|
||
| Tokens motion | `src/lib/motion/tokens.ts` | `prefersReducedMotion()`, `syncopatedDelay(i)` (3+3+2) |
|
||
| Reveal | `src/lib/motion/reveal.ts` | `use:reveal={index}` â cascade gwoka |
|
||
| Tilt | `src/lib/motion/tilt.ts` | `use:tilt` â CSS `--rx/--ry` |
|
||
| KineticText | `components/motion/KineticText.svelte` | `<KineticText text as="h2" class="section-title" />` |
|
||
| ScrollProgressBar | `components/motion/ScrollProgressBar.svelte` | global, gradient orâvert |
|
||
| IntroLoader | `components/motion/IntroLoader.svelte` | cérémonie 1re visite, skippable |
|
||
| Marquee | `components/motion/Marquee.svelte` | `<Marquee {t} />` |
|
||
| FlagChip | `components/motion/FlagChip.svelte` | ornement de titre, dessin au scroll |
|
||
| Images | `components/ResponsiveImage.svelte` + `imagetools.d.ts` | `import pic from './x.png?format=avif;webp;png&w=âŠ&as=picture'` â `<ResponsiveImage picture={pic} alt />`. **Le wildcard `declare module '*&as=picture'` doit vivre dans un `.d.ts` NON-module** |
|
||
| Sprite OKI | `static/icons.svg` | 12 pictos KA (§1.8) â `<use href="/icons.svg#ID">` |
|
||
| Logos marques | `components/icons/BrandIcon.svelte` | `<BrandIcon name="mastodon|peertube|nextcloud|gitea|castopod|discord|telegram|whatsapp|email|stoat|tiktok|x" />` |
|
||
| Village | `components/sections/HostingVillage.svelte` | scÚne SVG écosystÚme + fallback grille |
|
||
| Nav/Footer | `components/Nav.svelte`, `Footer.svelte` | nav active (IO), dropdown accessible, thÚme, langue ; footer fédéré |
|
||
| Emojisâpictos | `components/sections/pictos.ts` | `splitLeadingEmoji(str)`, `pictoFor(emoji)` |
|
||
| Bridge tokens | `atlas-fediverse/src/styles/oki-bridge.css` | alias des anciens noms de tokens vers la charte â applique la charte Ă un projet existant **sans retoucher chaque composant** |
|
||
| Layout bakĂ© | `atlas-fediverse/scripts/build-layout.mjs` | d3-force en script node â positions dĂ©terministes figĂ©es en JSON (init hashĂ©e FNV-1a + ticks fixes = bit-identique). Rejouer quand les donnĂ©es changent |
|
||
| Ătat partagĂ© inter-sections | `atlas-fediverse/src/lib/software-modal.svelte.ts` | module `$state` + `requestX()/consumeX()` : ouvrir une modale d'un composant depuis une autre section (timeline â catalogue) |
|
||
| Layout app 100dvh | `JWE/app/src/lib/styles/jeu.css` | `height: 100dvh` (pas min-height) + overflow par panneau + overlays consolidĂ©s (une puce de statut, rangĂ©es de boutons hors de la carte, barre d'actions opaque z-indexĂ©e) â zĂ©ro scroll, zĂ©ro superposition |
|
||
| Count-up score | `JWE/app/src/lib/motion/countup.ts` | `use:compte={cible}` : rAF â Ă©criture DOM directe, span animĂ© `aria-hidden` + valeur finale en `.sr-only` (rĂ©gion `aria-live`) |
|
||
| Reveal SSR | `JWE/app/src/lib/motion/reveal.ts` | variante dont l'état initial est rendu cÎté serveur, masqué uniquement sous `html.js` + `no-preference` |
|
||
| i18n dossiers | `gwada-sirius/src/lib/i18n/index.ts` | catalogues au format Paraglide/inlang consommĂ©s par un routeur maison (pas de middleware) â statique-friendly, l'outillage inlang reste utilisable |
|
||
| Support volume iOS | `svelte-podcast/src/lib/volume-support.ts` | `can_set_volume()` : sonde l'Ă©criture de `volume` sur un Ă©lĂ©ment jetable (mĂ©moĂŻsĂ©e) â dĂ©tecte iOS par capacitĂ©, pas par UA sniffing |
|
||
| PWA | `vite.config.ts` (bloc VitePWA) + `static/registerSW.js` + `static/manifest.webmanifest` | voir §2.9 |
|
||
| Headers | `static/.htaccess` + `static/_headers` | voir §2.10 |
|
||
| 404 / offline | `static/404.html` + `routes/+error.svelte` + `routes/offline/` | KA + tambour `ka`, autonomes |
|
||
|
||
---
|
||
|
||
## 5. LEĂONS DE LA MIGRATION o-k-i.net (piĂšges dĂ©jĂ rĂ©solus â ne pas les rĂ©-apprendre)
|
||
|
||
1. **Toujours auditer le dĂ©pĂŽt rĂ©el** : le brief disait « HTML statique », c'Ă©tait Eleventy + i18n JSON. Le contenu vivait dans les donnĂ©es â les reprendre, pas réécrire.
|
||
2. **Les données priment sur le brief** : le village suit `services.json` (4 instances), pas les exemples du brief ; la section cible se décide d'aprÚs le contenu JSON, pas le titre supposé.
|
||
3. **vite preview meurt si l'on rebuilde pendant qu'il tourne** (il sert `.svelte-kit/output`) â redĂ©marrer aprĂšs chaque build.
|
||
4. **CSP `script-src 'self'`** : anti-FOUC, lang-redirect et registerSW en fichiers externes statiques ; aucun inline.
|
||
5. **Preview headless** : `--virtual-time-budget` fige les animations d'entrĂ©e (faux nĂ©gatifs visuels) â valider le motion en temps rĂ©el via puppeteer (`--no-save`), pas en screenshot one-shot.
|
||
6. **Puppeteer QA** : `page.emulateMediaFeatures` pour reduced-motion ; le tilt se teste par `dispatchEvent(PointerEvent)` (le scroll Lenis décale `mouse.move`).
|
||
7. **eslint/autofixer `no-navigation-without-resolve`** : `resolve()` pour routes internes, `asset()` pour fichiers statiques, `rel="external"` pour sortir du scope de la rĂšgle â sans jamais envelopper une URL externe ou une ancre `#`.
|
||
8. **Grep de vĂ©ritĂ©** avant de livrer : zĂ©ro domaine tiers dans `build/` (hors liens `<a>` mĂ©tier), zĂ©ro emoji dans le HTML buildĂ©, toutes les URLs en 200, `og:` Ă10, JSON-LD prĂ©sents.
|
||
9. **Lighthouse aprĂšs chaque passe** (mobile) et corriger ce qui est remontĂ© â les deux points gagnĂ©s sur o-k-i.net : `aria-label` sur span (KineticText) et liens non soulignĂ©s.
|
||
10. **Lighthouse `link-in-text-block`** : scoper `text-decoration: underline` Ă `main` â sinon la nav et le footer hĂ©ritent de soulignĂ©s partout.
|
||
|
||
## 5b. LEĂONS DES MISSIONS atlas / exitchatcontrol / gwada-sirius / JWE
|
||
|
||
**Gouvernance & process**
|
||
1. **git d'abord** : atlas n'avait aucun dĂ©pĂŽt â `git init` + commit de l'existant avant toute ligne de code.
|
||
2. **WIP non commité d'autrui** : builder d'abord ; si c'est cohérent, committer tel quel, puis améliorer par commits séparés (exitchatcontrol).
|
||
3. **Orchestration d'agents parallĂšles** : sĂ©rialiser tout ce qui touche `package.json` / npm (un seul agent ou le parent) ; dĂ©finir les contrats (props des composants, noms de tokens, chemins) AVANT de lancer â les agents s'intĂšgrent alors sans conflit, et dĂ©couvrent mĂȘme le travail des autres (module `software-modal` rĂ©utilisĂ© en vol).
|
||
4. **Conflits de ports** : avant tout audit automatisĂ©, vĂ©rifier ce qui tourne (`vite preview` d'un autre projet sur le mĂȘme port a faussĂ© un audit axe â vĂ©rifier le `<title>` servi).
|
||
|
||
**Technique SvelteKit**
|
||
5. **`paths.relative: false`** quand `paths.base` est utilisĂ© : par dĂ©faut `$app/paths.base` vaut `".."` au prerender, ce qui casse toutes les comparaisons de pathname (`startsWith(base)`, switcher de langue, `aria-current`) et produit des hrefs relatifs bizarres dans le HTML prĂ©rendu. L'hydratation masque le bug â le vĂ©rifier dans le HTML buildĂ©, pas seulement au clic.
|
||
6. **`lang` par route avec base path** : retirer `base` dans `hooks.server.ts` AVANT de déduire la locale du premier segment.
|
||
7. **i18n sans middleware** : un routeur par dossiers (`/`, `/en/`, `/ht/`) + loader JSON maison bat Paraglide-officiel pour le statique (URLs et prerender sous contrĂŽle total) tout en gardant les catalogues au format inlang.
|
||
8. **Ălots â composants natifs** : le montage manuel (`mount.js` + IntersectionObserver) disparaĂźt ; le fallback SSR (table, liste) devient le markup mĂȘme du composant â meilleur pour no-JS ET pour le CLS.
|
||
9. **Leaflet sous SSR** : `await import('leaflet')` dans `onMount` (l'import statique plante cÎté Node), CSS en import statique OK, `L.divIcon` CSS au lieu d'images de marqueurs. Tuiles OSM = exception documentée au zéro-tiers, à faire trancher par le propriétaire.
|
||
10. **CSP d'un jeu/app riche** (adapter-node â `hooks.server.ts`) : Ă©numĂ©rer les domaines rĂ©els en inspectant le code ET les node_modules (Mapillary a besoin de `graph.` + `tiles.` + `images.mapillary.com`, Wikimedia d'`upload.` + `commons.`) â puis jouer une manche complĂšte en capturant la console : zĂ©ro violation exigĂ©e.
|
||
11. **Layout « app » sans scroll** : `height: 100dvh` (jamais `min-height`) + overflow géré par panneau + indices dans des panneaux scrollables internes. Les bugs de superposition mobile viennent d'overlays absolus empilés : consolider les badges en une puce, sortir les rangées de boutons de la carte, barre d'actions opaque avec `z-index` explicite, `pointer-events: none` sur tout conteneur décoratif. Tester chaque bouton par `elementFromPoint`.
|
||
12. **Le « moment de rĂ©vĂ©lation »** (jeux) : ligne de distance dessinĂ©e + score en count-up + marqueur qui tombe. Count-up : rAF â DOM direct, jamais d'Ă©tat rĂ©actif par frame ; span animĂ© `aria-hidden` + valeur finale `.sr-only` dans une rĂ©gion `aria-live`.
|
||
13. **CSP hashĂ©e** (script postbuild qui hashe les inline) : un JSON-LD inline ajoutĂ© est hashĂ© automatiquement â mais vĂ©rifier le compte d'empreintes aprĂšs build.
|
||
14. **IcĂŽnes PNG lourdes** : `PIL.Image.quantize(256)` suffit pour des logos (121 Ko â 9 Ko, perte invisible) â toujours relire l'image aprĂšs.
|
||
|
||
**Contenu & données**
|
||
15. **Audit factuel des donnĂ©es** en plus de l'audit technique : la timeline d'atlas contenait 4 dates fausses et un compteur pĂ©rimĂ© (Twitter 2021â2022, Mastodon 2015â2016, PeerTube 2015â2017, Bluesky 2023â2024, « 55+ »â105). Les champs de donnĂ©es inutilisĂ©s (`month`, `softwareId`) sont souvent des fonctionnalitĂ©s gratuites.
|
||
16. **RĂ©gressions SEO typiques au changement de gĂ©nĂ©rateur** : sitemap, OG hors fiches, og:image, canonical â checklist Ă passer systĂ©matiquement (exitchatcontrol).
|
||
|
||
**Déploiement YunoHost**
|
||
17. Le package ne consomme que des **archives de tag** : taguer l'app (`vX.Y.Z`), pousser le tag, télécharger l'archive `/archive/<tag>.tar.gz` depuis la forge, recalculer son sha256, mettre à jour `manifest.toml` (version `X.Y.Z~ynhN` + url + sha256), commit/push le package. `autoupdate.strategy = "latest_forgejo_tag"` détecte les tags suivants.
|
||
|
||
## 5c. LEĂONS DE LA MISSION oki-podcast-reader (lecteur audio)
|
||
|
||
**Gouvernance & forks**
|
||
1. **SĂ©curiser le WIP AVANT tout** : toute la transformation applicative Ă©tait non commitĂ©e sur un fork â premier commit de protection avant la premiĂšre analyse dĂ©taillĂ©e (rĂšgle gĂ©nĂ©rale : `git add -A && git commit "WIP sĂ©curisĂ©"` dĂšs qu'un working tree contient du travail non versionnĂ©).
|
||
2. **Fork de librairie â application** : purger la dette de packaging (champs `exports`/`files`/`peerDependencies`, changesets, publint, workflows CI de la lib) â le `package.json` d'une app est `private: true` et nu.
|
||
3. **Le remote `origin` d'un fork pointe chez l'auteur original** : le renommer `upstream` avant d'ajouter le remote de déploiement, sinon le push part chez l'original (échoue ou pire).
|
||
|
||
**Upgrades de framework**
|
||
4. **Le mode compat Svelte 5 est une voie complĂšte** : SvelteKit 1â2 + Svelte 4â5 SANS réécriture en runes â la syntaxe legacy (`on:click`, `$:`, `export let`, `<slot>`) compile Ă 0 erreur/0 warning. Upgrader les paquets, traiter uniquement les breaking changes (imports `vitePreprocess`, options TS supprimĂ©es, sĂ©rialisation), ne JAMAIS réécrire la syntaxe dans la mĂȘme passe. La réécriture en runes est une mission sĂ©parĂ©e, facultative.
|
||
5. **Respecter le gestionnaire de paquets du projet** (yarn.lock â package-lock.json) â ne pas mĂ©langer.
|
||
|
||
**RÚgle d'architecture des loads (la plus généralisable)**
|
||
6. **Universal load (`+page.ts`) = le corps brut des fetch est inlinĂ© dans le HTML** : un flux RSS de 10 Mo produisait une page de 11,9 Mo. **Server load (`+page.server.ts`) garde le fetch cĂŽtĂ© serveur** â rĂšgle d'un coup : bloat supprimĂ© (â88 %), ET les problĂšmes CORS en navigation client disparus (le navigateur ne refait jamais le fetch : il lit `__data.json`). Toute donnĂ©e tierce fetchĂ©e appartient Ă `+page.server.ts`. Corollaire : les pages qui en dĂ©pendent ne buildent pas hors-ligne â Ă documenter.
|
||
7. Les redirections CORS se contrĂŽlent Ă chaque saut : une 302 sans `Access-Control-Allow-Origin` tue le fetch navigateur mĂȘme si la destination finale l'autorise â raison de plus pour fetcher cĂŽtĂ© serveur.
|
||
|
||
**Audio / média**
|
||
8. **Les prĂ©fĂ©rences mĂ©dia persistĂ©es doivent ĂȘtre re-appliquĂ©es en continu** (souscription), pas seulement au chargement de la source â et `?? 1`, jamais `|| 1` (un 0 persistĂ© est une valeur lĂ©gitime).
|
||
9. **`HTMLMediaElement.volume` est en lecture seule sur iOS** : détecter par capacité (sonder l'écriture sur un élément jetable, mémoïser), masquer le slider, garder le mute (`el.muted`, lui, fonctionne). Source de vérité unique dans le store persisté, synchronisée dans les deux sens.
|
||
10. **Cibles tactiles sur les lecteurs** : Ă©paisseur visuelle â zone de hit (piste fine de 10 px OK si la zone fait 44 px). Un `<input type="range">` ne repositionne PAS le thumb au tap tactile â handlers `touchstart`/`touchmove` explicites requis (tester avec `page.tap` + `hasTouch`).
|
||
11. **Media Session API est non négociable pour une app audio** (contrÎles écran verrouillé) : `metadata` à chaque piste + handlers `play`/`pause`/`previoustrack`/`nexttrack`, gardé par `'mediaSession' in navigator`.
|
||
12. **SW d'une app audio** : ne JAMAIS intercepter les streams (requĂȘtes `Range`, extensions mĂ©dia) â prĂ©cache shell, cache-first sur pochettes uniquement.
|
||
|
||
**Perf de listes**
|
||
13. **`content-visibility: auto` + `contain-intrinsic-size`** : le gain de perf de listes le moins cher qui existe (CSS seul). Avant toute virtualisation : pagination « charger plus » 50Ă50 (1022 lignes DOM â 50).
|
||
|
||
---
|
||
|
||
## 6. PATTERNS AWWWARDS (distillĂ© des 15 sites â quoi voler, Ă quel coĂ»t)
|
||
|
||
| Pattern (source) | Coût | Statut pour OKI |
|
||
|---|---|---|
|
||
| DOM-only masks/clip-path « 3D » (Zentry) | 5 % du coût GPU | **Adopté** (wipes pochettes) |
|
||
| Motion system spec'd avant les pages (Zentry, P4) | 0 | **Adopté** (tokens gwoka) |
|
||
| Hover craft budgĂ©tĂ© â 5 interactions intentionnelles (Noomo) | faible | **AdoptĂ©** (balayage boutons, tilt, soulignĂ©s, village) |
|
||
| Loader-as-fiction (KPR) | faible | **Adopté** (IntroLoader) |
|
||
| Ătats designĂ©s : 404, vide, offline (Studio375) | faible | **AdoptĂ©** (KA + tambour) |
|
||
| Dollhouse IA â sections = lieux physiques (Kriss.ai) | moyen | **AdoptĂ©** (village crĂ©ole) |
|
||
| Constellation zetwal (charte §7 â prescription portails fĂ©divers) | faible | **AdoptĂ©** (hero atlas, remplace un shader Three.js de 708 Ko) |
|
||
| Layout bakĂ© au build â positions de graphe figĂ©es (dĂ©clinaison P2) | faible | **AdoptĂ©** (carte atlas : SVG 2D dĂ©terministe, â750 Ko de JS) |
|
||
| Moment de rĂ©vĂ©lation designĂ© â ligne de distance + count-up + chute de marqueur (jeux) | faible | **AdoptĂ©** (JWE) |
|
||
| Bilingual kinetic type â la bascule de langue comme Ă©vĂ©nement (Nudot) | faible | **Candidat** (Ă©volution du lang-switch FR/KA) |
|
||
| Chaptered scroll-comic (ten.375.studio) | moyen | **Candidat** (lore DJANGOKAM, patrimoine) |
|
||
| Scroll flipbook connection-aware (Apple) | moyen | **Candidat** si séquence visuelle un jour (gating `effectiveType` obligatoire) |
|
||
| Bake noise/textures offline (David Whyte) | faible | **Candidat** (fonds génératifs bakés) |
|
||
| Backstage / process public (Immersive Garden) | faible | **Candidat** (contenu pédagogique = souveraineté) |
|
||
| Cursor-as-light, velocity particles (Unseen, Igloo) | élevé | **Rejeté** (audience tactile) |
|
||
| WebGL full-UI (Igloo), skeletal scroll camera (HAPE), flipbook géant | trÚs élevé | **Rejeté** (budgets 4G/Mali-G52) |
|
||
| Resolution gating (KPR) | â | **Interdit** (hostile mobile) |
|
||
|
||
---
|
||
|
||
## 7. TEMPLATE DE BRIEF DE MISSION (Ă remplir par projet)
|
||
|
||
```markdown
|
||
# MISSION : [Transformer X / Créer Y] selon le PLAYBOOK UNIFIà OKI à SVELTEKIT
|
||
|
||
## 1. Contexte
|
||
- Site/projet : [URL/dĂ©pĂŽt] â stack actuelle mesurĂ©e : [Ă auditer, §2.4 phase 1]
|
||
- Identité : [association/projet, positionnement]
|
||
- ĂcosystĂšme liĂ© (liens externes Ă prĂ©server) : [liste]
|
||
- Bugs de production confirmés : [liste audit]
|
||
|
||
## 2. Contenu éditorial
|
||
- [Reprendre à l'identique / réécriture autorisée : périmÚtre]
|
||
- Langues : [FR / EN / KA â URLs]
|
||
|
||
## 3. Exigences techniques
|
||
- Stack : §2.3 du playbook (dĂ©faut) â Ă©carts Ă©ventuels : [liste]
|
||
- URLs Ă conserver : [liste + ancres]
|
||
- Hébergement cible : [o2switch statique / Cloudflare Pages]
|
||
- PWA : [oui/non]
|
||
|
||
## 4. Motion & composants (sĂ©lection depuis §2.6 â rester sobre)
|
||
- [ ] KineticText titres [ ] IntroLoader [ ] Marquee [ ] Village/scĂšne
|
||
- [ ] Autre : [prĂ©ciser] â WebGL : [non par dĂ©faut]
|
||
|
||
## 5. PérimÚtre de cette session
|
||
- [ ] âŠ
|
||
|
||
## 6. CritĂšres d'acceptation
|
||
- DoD §8 intégralement vérifiée + [spécifiques projet]
|
||
```
|
||
|
||
---
|
||
|
||
## 8. DOD â DĂFINITION DE « TERMINà » (tout doit ĂȘtre vrai)
|
||
|
||
**Fondations**
|
||
- [ ] Rapport d'audit livré ; bugs pré-existants corrigés ou explicitement reportés · **git vérifié/initialisé avant tout travail**.
|
||
- [ ] Tokens charte importés (fichier partagé, pas de valeurs recopiées) ; thÚme sombre défaut, clair opt-in AA.
|
||
- [ ] Fonts self-hĂ©bergĂ©es ; zĂ©ro requĂȘte tierce au chargement (vĂ©rifiĂ© onglet rĂ©seau + grep du build).
|
||
- [ ] `npm run check` : 0 erreur, 0 warning · `npm run build` vert · `svelte-autofixer` propre sur les fichiers modifiés.
|
||
- [ ] Si `paths.base` : `paths.relative: false` et hrefs du HTML prérendu inspectés (pas de `../` ni de double préfixe).
|
||
- [ ] **Audit factuel des données** (dates, compteurs, champs inutilisés) en plus de l'audit technique.
|
||
- [ ] Toute donnée tierce fetchée passe par `+page.server.ts` (un universal load inline le corps brut des fetch dans le HTML).
|
||
|
||
**Marque**
|
||
- [ ] Or = seule couleur d'action ; rouge/vert dans leurs rÎles · angles nets (†6 px).
|
||
- [ ] Flag-bar segments francs, †1 pleine largeur par écran · zéro emoji en interface (sprite SVG).
|
||
- [ ] Tokens motion gwoka + stagger syncopé · gate `prefers-reduced-motion` vérifiée manuellement.
|
||
- [ ] Voix conforme (test : aucune occurrence de « clé en main », « solution innovante », « disruptive »).
|
||
|
||
**Expérience & accessibilité**
|
||
- [ ] Navigation clavier complĂšte (tab order, focus visible, skip-link, village/scĂšne/carte focusable).
|
||
- [ ] **Zéro superposition** : chaque bouton testé par `elementFromPoint` (mobile 390 px) ; `pointer-events: none` sur tout conteneur décoratif.
|
||
- [ ] Layout app : `height: 100dvh` si « tout visible sans scroll » est exigĂ© â `scrollHeight === innerHeight` mesurĂ© mobile ET desktop.
|
||
- [ ] Page fonctionnelle et lisible avec JS désactivé.
|
||
- [ ] 404, vide et hors-ligne designés (KA + tambour) · loader designé si présent, skippable.
|
||
- [ ] `lang` correct par locale · hreflang · OG complet self-hébergé · JSON-LD.
|
||
|
||
**Mesures**
|
||
- [ ] Lighthouse mobile : Performance ℠90, Accessibilité ℠95, Best Practices ℠95, SEO ℠95.
|
||
- [ ] JS initial †170 Ko gzip · accueil †2 Mo · images optimisées (aucune > 200 Ko hors hero, lazy hors LCP).
|
||
- [ ] Toutes les URLs historiques préservées ou redirigées · sitemap/robots à jour.
|