Files
annu-kute-ced/doc2sveltekit-transition/recette-sveltekit-15-sites-awwwards.md
sucupira d6efb6736f Réécriture SvelteKit statique (Svelte 5 runes + TS, adapter-static)
- 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
2026-07-23 00:49:02 -04:00

61 KiB
Raw Permalink Blame History

15 Award Sites → The SvelteKit Recipe

An autopsy of Awwwards-grade websites + an actionable implementation guide for Cyber-mawonaj

Method note. Stack claims are grounded in official case studies, Awwwards entries and technical write-ups wherever they exist (footnotes at the end of the document). Where no public source exists (marked inference), the analysis is based on observable rendering behavior and the studio's known toolchain. Every "stealable pattern" is something you can extract without the original codebase.


PART 1 — SITE-BY-SITE ANALYSIS


1. unseen.co — Unseen Studio (Bristol, UK)

Unseen Studio is the rebrand of Green Chameleon, a studio with 35 SOTDs; their own site won SOTD at launch 1 2 .

[A] Visual language. Dark, atmospheric base with volumetric lighting as the signature — their designers publish "volumetric lighting studies" as R&D, and that light-fog sensibility pervades the site 2 . Palette: near-black grounds, soft chromatic blooms (rainbow-adjacent volumetric glows), restrained UI chrome. Typography is large, confident grotesque with generous tracking; type never competes with the 3D — it floats above it. Composition is free-form asymmetry around a central 3D stage.

[B] Motion. Physics-feeling, inertia-heavy. Real-time WebGL particle simulations are an in-house specialty (they teased a "real-time WebGL particle sim" before project launches) 2 . Scroll acts as a camera dolly through project worlds; hover states distort or illuminate the medium rather than underline links. Cursor is part of the lighting rig.

[C] Tech stack. WebGL/Three.js confirmed by their own hiring and project tags (#webgl #threejs) 2 . Custom shader work for volumetrics and particles; DOM reserved for text/UI. Performance strategy: the studio iterates "directly in the browser" with live shader reloading.

[D] UX. Scroll-driven portfolio-as-journey. Navigation is minimal; the work is the menu. Accessibility trade-off: heavy reliance on pointer + WebGL, text contrast sometimes sacrificed to atmosphere. Mobile gets a simplified but genuine version, not a broken one.

[E] Critical assessment.

  • Strengths: (1) volumetric light identity — instantly recognizable; (2) particle/cursor integration makes the UI feel alive; (3) brand confidence: the site demonstrates the product instead of describing it.
  • ⚠️ Weaknesses: (1) WebGL-first means a hard floor for low-end devices; (2) atmosphere-over-contrast hurts readability on cheap screens.
  • 🔓 Stealable pattern: the cursor-as-light-source — pass pointer position as a uniform to your scene shader so the user literally illuminates content. One uniform, huge perceived interactivity.

2. animejs.com — Anime.js v4 (Julian Garnier)

The v4 relaunch site (2025) went viral in r/webdev as "just incredible" — the 3D hero scene is Three.js, everything else is animated with the library itself as a living demo 3 .

[A] Visual language. Deep-space dark UI, electric accent colors, dot-grid/blueprint textures referencing engineering drawing. Typography: technical sans with tabular numerals, kinetic type everywhere — the docs headlines themselves animate. Atmosphere: glassy panels + grain, "lab instrument" aesthetic.

[B] Motion. The philosophy is the product: timeline-orchestrated, stagger-driven, spring-eased. The v4 API is modular — animate, createTimeline, createScope, createSpring, stagger, splitText, createDraggable are separate named imports 4 . Scroll Observer API syncs animations to scroll with multiple sync modes and thresholds 5 . Micro-interactions: every parameter knob in the docs is draggable and live-updates the demo.

[C] Tech stack. Three.js for the hero scene; Anime.js v4 for all DOM/SVG animation 3 . Tree-shakeable ESM modules — you import only animejs/animation, animejs/timeline, etc. 4 . This modularity is itself a lesson: ship ≤ what you use.

[D] UX. Documentation as experience: interactive playground embedded in the narrative. Accessibility: motion-heavy but each demo is self-contained; reduced-motion handling is left to the implementer (a gap).

[E] Critical assessment.

  • Strengths: (1) product demonstrates itself — zero stock imagery; (2) interactive docs collapse learning time; (3) spring physics defaults feel modern vs. GSAP's classic easings.
  • ⚠️ Weaknesses: (1) animation overload can fatigue on long doc sessions; (2) no first-party reduced-motion story.
  • 🔓 Stealable pattern: createScope per component — scope animation queries to a component root and revert() on cleanup. Maps 1:1 to Svelte's component lifecycle (see §6).

3. immersive-g.com — Immersive Garden (Paris)

3× Awwwards Studio of the Year, 90+ awards; the 2025 rebuild won SOTM and is fully documented in an official case study 6 7 .

[A] Visual language. Minimalist-yet-atmospheric: bas-relief 3D compositions of natural elements, Roman numerals rendered in 3D as menu anchors, muted stone/bone palettes with deep shadows 7 . It's "digital craftsmanship" as brand — tactile, sculptural, almost geological.

[B] Motion. Restrained and ceremonial. GSAP for transitions, Lenis for scroll 7 . Nothing bounces; everything glides. The wow is in scene transitions and reveal choreography, not jitter.

[C] Tech stack (confirmed): Three.js + Blender/Houdini/ZBrush asset pipeline; Vue/Nuxt frontend; GSAP + Lenis; Strapi + Node backend; Vercel deployment 7 . Performance strategy is the headline: server-side KTX GPU texture compression, channel-packed textures, gltf-transform automated exports with custom Blender/JS scripts 7 .

[D] UX. One-click access navigation doctrine: any case study reachable in a single interaction. The "Backstage" section — behind-the-scenes technical breakdowns per project — is a hidden-gem IA pattern that turns process into content 7 .

[E] Critical assessment.

  • Strengths: (1) compression pipeline is industry best practice (KTX + channel packing); (2) Backstage = transparency as marketing; (3) minimalism with one strong sculptural motif instead of ten effects.
  • ⚠️ Weaknesses: (1) Strapi + Node backend adds hosting weight you'd feel on a 50 €/mo budget; (2) realism-first 3D = large asset payloads even compressed.
  • 🔓 Stealable pattern: the Backstage section — document your process publicly per project. For Cyber-mawonaj this doubles as pedagogical content (open knowledge = sovereignty).

4. davidwhyte.com/experience — David Whyte Experience (by Immersive Garden)

SOTM Dec 2024; official case study available 8 9 .

[A] Visual language. Watercolor paintings by Matthew Phinn as the entire visual substrate — organic pigment bleeds, paper texture, muted landscape hues. Typography is literary serif, quiet. This is the anti-neon site: proof that "immersive" doesn't mean cyber.

[B] Motion. Two hero techniques: a cursor-driven watercolor fluid simulation — one fluid sim per visible painting, optimized via a simulation atlas + stencil buffer so only active paper regions compute 9 ; and a generative watercolor reveal — noise-layered droplets dissolving the painting into view, with noise baked in advance to avoid real-time cost 9 . Long-press reveals video of the real location.

[C] Tech stack (confirmed): Nuxt/Vue, Sass + BEM, Three.js (Blender-driven camera recreated in WebGL, custom shaders), GSAP, Lenis, WordPress CMS, Vercel 9 .

[D] UX. Scroll through landscapes; each poem gets full-screen focus. Long-press is a deliberate slow-interaction — forces contemplation, matches the content's tempo. Accessibility: text remains real DOM text (good); the fluid sim is decorative-only (also good).

[E] Critical assessment.

  • Strengths: (1) baked-noise reveal = generative feel at zero runtime cost; (2) stencil-buffer atlas is a genuinely clever perf pattern; (3) motion tempo matched to content (slow poetry, slow interaction).
  • ⚠️ Weaknesses: (1) fluid sim still taxes low-end GPUs; (2) long-press is undiscoverable without onboarding hints.
  • 🔓 Stealable pattern: bake your noise — precompute generative textures offline (Blender/Python/ComfyUI for you), ship them as KTX2, blend in shader. Generative look, static-asset perf. Perfect fit for your ComfyUI pipeline.

5. kriss.ai/home/aftercare — Kriss.ai (by Studio 28K)

Awwwards case study available 10 .

[A] Visual language. Deliberate rejection of "cold AI tech" aesthetics: 70s-inspired palette, organic shapes, soft warm tones — a dental AI presented as a human service 10 . The whole site is a "Dollhouse": an open 3D cutaway of a dental clinic where each room (front desk, surgery, aftercare) is a content section.

[B] Motion. Spatial navigation through the dollhouse: camera moves between rooms on scroll/click. Motion serves wayfinding — you always know where you are in the building, hence in the offer.

[C] Tech stack (confirmed): WebGL 3D built in Blender; deployed on Cloudflare Pages + R2 for media — a notable choice: heavy visual assets on an edge CDN, zero traditional backend 10 . Figma → Blender → VSCode pipeline.

[D] UX. Metaphor-driven IA: product features mapped to physical rooms. This collapses the learning curve for non-technical buyers (dentists) — the spatial metaphor carries the explanation.

[E] Critical assessment.

  • Strengths: (1) narrative pivot "from tech to human" executed in the medium itself; (2) dollhouse = site map you can see; (3) Cloudflare Pages/R2 architecture proves you can host heavy WebGL at near-zero backend cost — directly relevant to your budget.
  • ⚠️ Weaknesses: (1) the 3D metaphor forces all content into rooms — awkward for dense text; (2) 70s warmth risks reading as dated outside the US market.
  • 🔓 Stealable pattern: the dollhouse IA — map AKILPA's or Cyber-mawonaj's sections to physical Caribbean spaces (case à ka, marché, karbay, plage). Navigation becomes cultural storytelling. Free pattern, no shaders required.

6. zentry.com — Zentry (by Resn)

Full Awwwards case study available — and the tech decision is the most instructive of all 15 sites 11 .

[A] Visual language. Bold, vibrant, "evil-corporation-playful": saturated color fields, chunky display type, 3D portal masks as signature motif. Sound-designed: dynamic soundtrack evolving from upbeat to ambient as you explore 11 .

[B] Motion. Motion system designed before the website: every reaction, curve and principle specced upfront 11 . Flashy, fast, reactive — but (see below) done entirely in DOM.

[C] Tech stack (confirmed): Nuxt/Vue + Vite, proprietary utility framework — and deliberately NO WebGL. The team needed massive DOM throughput (text, dynamic media) and chose to build the 3D portal-mask effects as custom DOM/CSS solutions instead of Three.js, explicitly to minimize complexity and maximize DOM performance 11 .

[D] UX. Portal motifs as content reveals; sound as orientation layer. The lesson: "immersive" is a design outcome, not a rendering technology.

[E] Critical assessment.

  • Strengths: (1) proof that award-grade "3D" can be pure DOM — transform3d, clip-path, masks, perspective; (2) motion-first design process (curves before comps); (3) sound design treated as first-class UX.
  • ⚠️ Weaknesses: (1) proprietary framework = not reproducible as-is; (2) audio autoplay remains an accessibility/UX minefield.
  • 🔓 Stealable pattern: DOM-only portal masksclip-path + transform-style: preserve-3d + a GSAP scrub timeline gives you 80% of the Zentry wow at 5% of the GPU cost. This is your #1 pattern for 4G/low-end Gwada devices.

7. igloo.inc — Igloo Inc (by Abeto + Bureaux)

SOTD Jul 2024 (7.92/10); unusually detailed case study + WebGPU showcase write-up 12 13 14 . And it's built in Svelte — your stack.

[A] Visual language. A frozen landscape: each portfolio project encased in a procedurally generated ice block (custom crystal-growth algorithm inside container shapes — unique every time, scales without manual modeling) 14 . Chromatic aberration + frost-dissolve scene transitions; intro sequence "between sci-fi title crawl and luxury brand ad" 14 .

[B] Motion. Camera drifts between scenes; footer is an interactive particle simulation that coalesces into different 3D shapes per hovered link, color shifting with particle velocity 14 . Text glitches via shaders; letter-scramble swaps SDF texture offsets instead of forcing DOM relayout — a performance decision doubling as a creative one 14 .

[C] Tech stack (confirmed): Three.js + Svelte + GSAP, Houdini + Blender, plus proprietary tooling including a custom VDB-to-browser exporter compressing volume data smaller than a typical website image 14 . Entire UI rendered in WebGL. Workflow: grey-box previs animations, then iterate directly in browser with real-time shader/model reloading, continuously measuring on low-end devices 13 .

[D] UX. Three sections only — the constraint forced a scroll experience dense with interaction 13 . Navigation = the journey itself.

[E] Critical assessment.

  • Strengths: (1) Svelte at the absolute top tier of the craft — kills any "can Svelte do this?" doubt; (2) procedural assets scale content without artists; (3) SDF-text-in-shader eliminates DOM relayout cost.
  • ⚠️ Weaknesses: (1) full-WebGL UI = screen-reader hostile, needs a parallel DOM layer; (2) proprietary VDB pipeline is not reproducible on a budget.
  • 🔓 Stealable pattern: velocity-reactive particles — map particle/element color or size to pointer velocity, not just position. Trivially implementable in a Svelte action ($derived from delta of pointer positions), huge tactile payoff. Also: SDF text rendering if you go WebGL-UI (troika-three-text does this for free).

8. kprverse.com — KPR (by Resn)

SOTD Dec 2022 (7.98) + SOTM; official making-of available 15 16 .

[A] Visual language. "New Eden" concept-art tableaux: hand-painted assets, bold concept-art style, terminal/console easter-egg aesthetics (fake file-system loading messages, "HTTPS://KPRVERSE.COM/KPCO/..." loader strings) 17 . Mixes 3D characters with 2D design elements, "interactive motion revealing a hidden dimension" 16 .

[B] Motion. Click-and-hold as the signature: holding reveals a second interactive layer (geography, factions, lifestyle of the world) 16 . Scroll moves through parallax tableaux (the Keep, the Factions, the World). Loading is theatrical: console-style progress theater.

[C] Tech stack. Resn proprietary (Nuxt-era Resn = Vue-based, per their Zentry write-up 11 ); layered 2D/3D compositing rather than full 3D scenes.

[D] UX. Narrative gating: lore revealed in layers, community invited to "shape the story". Notably hard device gating: "Your Browser resolution is currently not supported" and portrait-only enforcement on mobile 17 — a controversial but deliberate trade.

[E] Critical assessment.

  • Strengths: (1) click-and-hold "second layer" is a brilliant lore-delivery mechanic; (2) loader-as-fiction (terminal theater) turns wait time into worldbuilding; (3) tableaux = content with room for community contribution.
  • ⚠️ Weaknesses: (1) resolution gating is hostile — for Gwada's mobile-dominant reality this pattern is toxic; ship a degraded mode instead; (2) hand-painted asset volume = production cost.
  • 🔓 Stealable pattern: click-and-hold reveal layer — pointer-down starts a GSAP timeline that cross-fades a hidden info stratum; release reverses it. One timeline, two states, infinite narrative uses (patrimoine layers: colonial map ↔ créole map).

9. hape.io — HAPE (by Dogstudio/DEPT for Digimental)

SOTD Apr 2022 (7.84, dev award animations 9.4/10); official case study available 18 19 20 .

[A] Visual language. High-fashion-magazine web design: black/gold footer palette, editorial grids, the 3D ape treated like a couture model 18 19 .

[B] Motion. The HAPE walk is the scroll: page opens zoomed on the ape's head; scrolling rotates the camera and dollies out to reveal the full strutting character — a walk cycle art-directed for "attitude" and synchronized to a handpicked soundtrack 20 . A "hapewalk mode" hands rotation/zoom control to the user 20 .

[C] Tech stack (confirmed): custom OGL micro-framework — OGL (minimal-abstraction WebGL library) extended in-house with PBR rendering, skinning, post-processing and an animation player 19 . Built in 4 weeks 19 .

[D] UX. One character, one gesture (scroll), one attitude — radical focus. Results: 57K visitors launch month, 4.58 min average session 19 .

[E] Critical assessment.

  • Strengths: (1) scroll-synced skeletal animation with music sync is a masterclass in single-idea execution; (2) OGL proves you don't need Three.js if your needs are narrow; (3) fashion-editorial framing elevates NFT kitsch to design.
  • ⚠️ Weaknesses: (1) skinned 3D + PBR is heavy for low-end mobile; (2) audio-synced motion degrades silently when sound is off/blocked.
  • 🔓 Stealable pattern: scroll-scrubbed skeletal camera — bind scrollProgress to a baked animation clip's time (mixer.setTime(progress * duration)). Works with any GLTF walk/dance cycle. Imagine it with a gwoka dancer or a lambi procession: cultural motion as scroll engine.

10. labs.noomoagency.com — Noomo Labs

Developer Award + SOTD 2024; official behind-the-scenes available 21 22 .

[A] Visual language. A dreamlike underwater journey with a glass jellyfish: 3D glass materials, refractive transparency, calm ambient sound design ("sound of the glass sphere appearing", music complementing the jellyfish) 22 . It's a hub for experiments — R&D made public.

[B] Motion. The technical doctrine: all 3D assembled in ONE Blender scene; all non-interactive animation (camera, jellyfish, words) baked in Blender; materials baked to textures 22 . Camera rigged to two Empties — one at the focal point, one animating the camera object 22 . Runtime = playback + interactive garnish.

[C] Tech stack (confirmed): Three.js + GSAP, explicitly avoiding React Three Fiber "to maintain flexibility", Nuxt framework, Blender-baked assets 22 . The storytelling sister site scrolls a Three.js camera through five differently-lit "rooms" of case studies 23 .

[D] UX. Labs = experiments before they "grow up" 23 — an institutional pattern: public R&D as marketing.

[E] Critical assessment.

  • Strengths: (1) bake-everything philosophy = cinematic quality at playback cost; (2) one-scene assembly avoids runtime scene-graph juggling; (3) labs-as-content is a sustainable publishing model.
  • ⚠️ Weaknesses: (1) baked = rigid; content changes require re-bakes; (2) glass/refraction shaders are expensive on Mali-class GPUs.
  • 🔓 Stealable pattern: the two-Empty camera rig — in Blender, parent your camera to a target-Empty + path-Empty, bake, export GLTF, and in SvelteKit just scrub cameraAnimation.time from Lenis scroll progress. Zero camera math at runtime. Your ComfyUI/Blender pipeline already supports this.

11. noomoagency.com — Noomo Agency

Awwwards Website of the Year winner 24 21 .

[A] Visual language. Glassmorphism at its most disciplined: glass cards on-scroll animations, 3D hover effects, a dynamic logo incorporating handwritten elements from each team member — personalization as brand system 24 25 . Boutique-agency warmth inside high-tech execution.

[B] Motion. "Every interaction and hover has its unique purpose" 24 — hover states are individually art-directed (button hovers, 3D case previews, showreel controls) 25 . Scroll animations drive case reveals; 3D transitions between pages.

[C] Tech stack (confirmed): Nuxt 3 front AND back (Node), Three.js + GSAP 24 .

[D] UX. Classic agency IA (work/story/contact) elevated by transition choreography — proof you don't need experimental IA if execution is flawless.

[E] Critical assessment.

  • Strengths: (1) hover-as-portfolio: micro-interactions individually designed, not defaulted; (2) humanizing details (handwritten logo) offset tech flex; (3) full-stack Nuxt keeps ops simple.
  • ⚠️ Weaknesses: (1) glass everywhere = blur = GPU cost on weak devices; (2) 3D page transitions can delay content access.
  • 🔓 Stealable pattern: budgeted hover craft — pick your 5 most-tapped elements and give each a unique, purposeful micro-interaction; leave the rest at system defaults. Award juries notice the ratio of intentional to generic interactions.

12. nudot.com.tw — Nudot (Taiwan)

No public case study found — this section is inference from the live site and studio profile; treat stack claims as low-confidence.

[A] Visual language. Taiwanese studio aesthetic in the lineage of Ultra Combos/Studio Pros: precise CJK+Latin bilingual typography, generous whitespace punctuated by abrupt kinetic moments, muted palette with one aggressive accent. Bilingual typesetting (Chinese vertical/horizontal + English) is itself the design flex.

[B] Motion. Text-led motion: character-level reveals, marquee systems, cursor-following media previews on project lists. Motion is typographic rather than 3D.

[C] Tech stack (inference). DOM/CSS + GSAP-class animation, canvas accents; likely Nuxt or similar Vue meta-framework (dominant in Taiwanese award studios).

[D] UX. Project-list-as-gallery with hover media previews; bilingual toggle as first-class nav item — relevant precedent for FR/KRÉ bilingual switching.

[E] Critical assessment.

  • Strengths: (1) bilingual typography treated as design material, not i18n afterthought; (2) restraint — effects deployed sparingly; (3) fast: typography-led sites are inherently light.
  • ⚠️ Weaknesses: (1) hover-previews have no touch equivalent (mobile gets a lesser list); (2) minimal feedback cues can confuse first-time visitors.
  • 🔓 Stealable pattern: bilingual kinetic type — design your FR/KRÉ switch as an animation event (lines rotate/mask-swap in place) rather than a page reload. Language toggle becomes brand moment. Implement with splitText + a shared-layout transition.

13. 375.studio/en/studio — Studio375 (Vicenza, Italy)

SOTD Apr 30, 2026 (7.33, plus Developer Award) [^2^]26 .

[A] Visual language. Two-color discipline (their earlier HM site was strict #000/#FFF) 27 , clean-flat-minimal portfolio aesthetic with colorful punctuations 27 . Communications-agency clarity rather than tech-lab showing-off.

[B] Motion. Hero image animation, mouse interaction, scroll-linked text decoration, animated 404 — a complete system of small moments rather than one big WebGL bet 27 . Dev-award scores show the craft is in transitions (animations 7.8, their strongest dev metric) [^2^].

[C] Tech stack (inference). DOM-first, GSAP-class orchestration; no heavy WebGL signature. Accessibility dev-score 7.2 is above the award-site average [^2^] — suggests semantic care.

[D] UX. Conventional studio IA executed with transition polish; even the 404 is a designed moment 27 .

[E] Critical assessment.

  • Strengths: (1) proves SOTD is achievable without WebGL; (2) systematic micro-motion (every page state designed, incl. errors); (3) strong accessibility score for the category.
  • ⚠️ Weaknesses: (1) less memorably distinctive than the WebGL cohort; (2) creativity scores (7.57) lag the experimental sites.
  • 🔓 Stealable pattern: design your error/empty/404 states with the same rigor as the hero. For an association site (AKILPA), the 404, the "no events yet", the offline page are touchpoints where grassroots personality can outshine budget.

14. ten.375.studio/en — "Ten Years Away" (Studio375)

SOTD Jun 26, 2026 (7.32; users rated creativity 9.3) 28 .

[A] Visual language. An interactive comic chronicling ten years of the studio — "real characters, real stories" 28 . Illustrated panels, comic-page composition translated to scroll, hand-drawn texture over digital precision.

[B] Motion. Mouse trail as a signature element, page transitions between comic chapters, intro sequence 28 . Motion serves panel-to-panel reading rhythm — scroll as page-turn.

[C] Tech stack (inference). DOM/SVG illustration + GSAP-class scrubbing; the comic format suggests asset sequencing rather than runtime 3D.

[D] UX. Narrative chronology as IA: ten years = ten chapters. Personal/historical storytelling instead of service listing — an anniversary site that earns attention through vulnerability (real people, real stories).

[E] Critical assessment.

  • Strengths: (1) format courage — a comic, not a portfolio grid; (2) chaptered narrative maps perfectly to scroll; (3) authenticity as differentiator (users scored creativity 9.3, far above jury 28 ).
  • ⚠️ Weaknesses: (1) niche payoff — low utility for prospective clients; (2) illustrated asset production is time-expensive.
  • 🔓 Stealable pattern: the chaptered scroll-comic — for AKILPA, a "10 dates du patrimoine gwada" or "l'histoire du lambi" as an interactive scroll-comic. Chapters = routes (/histoire/[slug]), panels = SVG/AI-generated assets (your Qwen/Seedream pipeline), transitions = shared-element morphs. High storytelling ROI per byte.

15. apple.com/airpods-pro — Apple

The canonical scroll-scrubbed product page; technique fully documented by CSS-Tricks and the GSAP community 29 30 .

[A] Visual language. Product-photographic maximalism on pure black; type appears only when the product pauses. No texture tricks — the hardware render is the visual language.

[B] Motion. Scroll-scrubbed image sequences: a 148-frame JPEG flipbook drawn to a fixed <canvas>, frame index = scroll fraction × frame count 29 . Content sections are one big master timeline with percentage-hand-picked timings; "fake pins" hold content in place 30 . requestAnimationFrame for tear-free frame swaps 29 .

[C] Tech stack (documented technique). Canvas 2D + image preloading; no WebGL needed 29 . Performance doctrine: on slow connections Apple ships a single fallback image instead of the sequence — and offers smaller sequences per device class 29 .

[D] UX. Scroll = product film. Information hierarchy: specs arrive only after desire is built. Accessibility: canvas content is mirrored by real DOM text below.

[E] Critical assessment.

  • Strengths: (1) the flipbook is the most copied award pattern alive — simple, robust, GPU-cheap; (2) explicit slow-network fallback strategy — exactly your 4G doctrine; (3) master-timeline percentage timing keeps everything in sync across viewports 30 .
  • ⚠️ Weaknesses: (1) 148 frames is a data hog without fallbacks; (2) canvas imagery needs parallel DOM for a11y/SEO.
  • 🔓 Stealable pattern: the scroll flipbook with connection-aware loadingnavigator.connection.effectiveType decides: full sequence / reduced frame set / single hero image. Ship it as a Svelte action (see §5, bonus component). This is the single most Gwada-appropriate award pattern in this list.


PART 2 — THE SVELTEKIT RECIPE

1. Core Principles (the common DNA)

Principle 1 — Scroll is the primary navigation driver. 13 of 15 sites bind narrative progression to scroll. Canonical stack: Lenis + GSAP ScrollTrigger, wrapped as Svelte actions/context (Immersive Garden ships exactly this combo 9 7 ). In SvelteKit: one Lenis instance in the root layout, exposed via context; never instantiate per component.

Principle 2 — Bake at build, not at runtime. David Whyte bakes noise 9 ; Noomo bakes camera, materials and character animation in Blender 22 ; Immersive Garden compresses textures server-side to KTX 7 ; Igloo compresses volumes to sub-image size 14 . Rule: if a value doesn't depend on live user input, it has no business being computed in the browser. Your ComfyUI/Blender pipeline is your "baking" layer — treat it as part of the build system.

Principle 3 — DOM first, WebGL only where it pays. Zentry did its award-winning "3D" portals in pure DOM deliberately 11 ; Apple's flipbook is Canvas 2D 29 . Reserve WebGL for: particle systems, fluid sims, real 3D assets with user-controlled cameras. Everything else: CSS transforms, clip-path, SVG. For 4G Guadeloupe this principle is non-negotiable.

Principle 4 — Motion is designed before pages. Zentry specced its motion system before design started 11 ; HAPE art-directed a walk cycle, then built a site around it 20 . Define your easing vocabulary, durations and rhythm (for you: gwoka cadences — see Part 3) as design tokens, before any component exists.

Principle 5 — Every state is a designed moment. Studio375's animated 404 27 , KPR's terminal-theater loader 17 , Noomo's per-element hover craft 24 . Loading, error, empty, offline: these are where personality lives when budget doesn't.


2. SvelteKit Architecture Patterns

2.1 Route structure for immersive experiences

src/routes/
├── +layout.svelte          ← SmoothScrollProvider (Lenis) + CursorTracker live HERE
├── +layout.ts              ← export const ssr = true (default)
├── (site)/                 ← layout group: classic content pages
│   ├── +page.svelte        ← home (light hero, DOM effects)
│   ├── histoire/[slug]/    ← chaptered scroll-comic (Ten Years Away pattern)
│   └── patrimoine/[slug]/  ← case studies, "Backstage" pattern (Immersive Garden)
├── (immersive)/            ← layout group: canvas-heavy experiences
│   ├── +layout.svelte      ← WebGLCanvas provider, ssr disabled per-page
│   └── mawonaj/+page.svelte
└── +error.svelte           ← designed 404 (Principle 5)

Rules:

  • Layout groups isolate the WebGL context to the routes that need it — the canvas provider never mounts on content pages.
  • Dynamic imports for anything heavy: const { WebGLCanvas } = await import('$lib/webgl/WebGLCanvas.svelte') behind {#await} or {#if browser} gates.
  • Progressive enhancement: every immersive route must render meaningful SSR HTML underneath the canvas (Apple mirrors its canvas with DOM text 29 — do the same).

2.2 Where WebGL lives

Use Svelte context, created once in the (immersive) layout:

// $lib/webgl/context.ts
import { setContext, getContext } from 'svelte';
import type * as THREE from 'three';

export interface WebGLContext {
  renderer: THREE.WebGLRenderer;
  scene: THREE.Scene;
  camera: THREE.PerspectiveCamera;
  canvas: HTMLCanvasElement;
}

const KEY = Symbol('webgl');
export const provideWebGL = (ctx: WebGLContext) => setContext(KEY, ctx);
export const useWebGL = () => getContext<WebGLContext>(KEY);

Child scenes register/unregister in $effect cleanup. One renderer per app, many scenes. Never two <canvas> WebGL contexts on one page for low-end targets.

For Three.js in Svelte, evaluate Threlte (the Svelte-native Three layer) for standard scenes, and raw Three.js for custom shader-heavy work (Igloo-style). Both coexist: Threlte components render into your single context.

2.3 Animation orchestration

Need Tool Why
Component enter/leave, list transitions Svelte built-in transitions (transition:, in:/out:) Zero deps, SSR-safe, cancellable
Scroll-scrubbed timelines, pinning GSAP + ScrollTrigger Industry standard on 11/15 sites
Lightweight springs, draggable, text splitting Anime.js v4 (modular imports) 4 ~5× smaller import surface when tree-shaken; createScope maps to component lifecycle
Physics cursor / spring values Anime.js createSpring or a 12-line custom spring No GSAP needed for this
One shared clock GSAP ticker as the single rAF driver, Lenis hooked into it Prevents competing rAF loops

3. CSS Architecture for Award Sites

3.1 Tailwind + CSS variables for dynamic theming

/* app.css — the theme lives in variables, Tailwind references them */
:root {
  /* Cyber-mawonaj tokens (see Part 3) */
  --lagune-phospho: oklch(72% 0.13 210);
  --roche-volcan:   oklch(18% 0.02 260);
  --corail:         oklch(70% 0.16 25);
  --or-circuit:     oklch(80% 0.14 90);
  --foret-neon:     oklch(55% 0.15 155);
  --ease-ka: cubic-bezier(0.22, 1, 0.36, 1);   /* motion tokens too */
  --dur-mesure: 480ms;
}
@theme inline {
  --color-lagune: var(--lagune-phospho);
  --color-volcan: var(--roche-volcan);
  /* … */
}

Theme switching = swapping a data-theme attribute on <html>, variables cascade, Tailwind utilities follow. No JS class churn, no FOUC if set in %sveltekit.head%.

3.2 Container queries > media queries for components

Media queries for page-level breakpoints; container queries for every reusable component (cards, chapters, nav). Award sites break layouts constantly because components are viewport-coupled; container queries make your KineticText or ParallaxLayer correct in a sidebar, a dialog, or a split-screen dollhouse room.

3.3 CSS that replaces JS

  • animation-timeline: scroll() / view() — native scroll-driven animations for parallax and reveals. ⚠️ Baseline 2023+: Chrome/Edge/FF OK; Safari 26+ only — keep a ScrollTrigger fallback for Safari < 26 (still common in Gwada's device pool). Flag: needs progressive enhancement wrapper.
  • scroll-snap for chaptered comics (Ten Years Away pattern) — free, native, accessible.
  • :has() for stateful styling (hovered card dims siblings) instead of JS class toggles.
  • View Transitions API for route morphs (see PageTransition, §5). ⚠️ Chrome/Edge/Safari 18+; Firefox behind flag — design as enhancement.

4. Performance Budget & Optimization

4.1 Budgets (mobile 4G, low-end Android — the Gwada baseline)

Resource Budget Rationale
JS initial (compressed) ≤ 170 KB ~1.7 s parse on entry-level 4G Android
WebGL textures ≤ 8 MB GPU RAM use KTX2/BasisU, never raw PNG to GPU 7
Models ≤ 500 KB per scene Draco or meshopt via gltf-transform 7
Hero media ≤ 400 KB before interaction poster + lazy sequence (Apple doctrine 29 )
Total page weight (home) ≤ 2 MB reality check against award sites' 8-15 MB
Frame budget 16 ms desktop / target stable 30 fps on Mali-G52 test on a real ~150 € Android, not DevTools throttling

4.2 WebGL asset pipeline

Blender → gltf-transform CLI:
  gltf-transform optimize in.glb out.glb \
    --compress meshopt --texture-compress ktx2
  • KTX2 + UASTC/ETC1S textures (Immersive Garden's exact strategy 7 ); channel-pack roughness/metallic/AO into one texture 7 .
  • LOD: two model tiers; pick at runtime from renderer.capabilities + deviceMemory.
  • Instancing for repeated elements (lambi shells, vegetation, stars).
  • Bake lighting into textures wherever the camera path is fixed (Noomo doctrine 22 ).

4.3 Animation frame budget

Concurrent JS-driven animations before jank on low-end: ~8-12 transform/opacity tweens. Beyond that: batch into one timeline, move to CSS, or cull off-screen animations (ScrollTrigger with toggleActions, or IntersectionObserver gating). Animate only transform and opacity — layout properties cause reflow (Anime.js v4 docs say the same 4 ).

4.4 SSR vs CSR for canvas pages

  • Canvas/WebGL pages: SSR the semantic content shell, hydrate the canvas client-side ({#if browser} + dynamic import). Don't disable SSR route-wide unless the page is truly content-free — you lose SEO and slow-connection resilience for nothing.
  • Lenis/GSAP init: onMount only, always.
  • SvelteKit prerendering (export const prerender = true) for everything static → perfect on Cloudflare Pages/Netlify free tiers, mirroring Kriss.ai's edge-CDN architecture 10 .

5. Component Library — Reusable Svelte 5 Modules

All components: Svelte 5 runes syntax, TypeScript, reduced-motion aware, cleanup on destroy.

5.1 SmoothScrollProvider — Lenis as layout-level context

<!-- $lib/components/SmoothScrollProvider.svelte -->
<script lang="ts">
  import { onMount, setContext, type Snippet } from 'svelte';
  import Lenis from 'lenis';
  import gsap from 'gsap';

  let { children }: { children: Snippet } = $props();
  let lenis: Lenis | null = $state(null);

  setContext('lenis', { get: () => lenis });

  onMount(() => {
    const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (reduced) return;                       // native scroll = the fallback

    lenis = new Lenis({ lerp: 0.1, smoothWheel: true });
    // ONE rAF driver for the whole app (Principle: shared clock)
    lenis.on('scroll', () => {});              // ScrollTrigger.update hook lives in KineticText
    gsap.ticker.add((t) => lenis?.raf(t * 1000));
    gsap.ticker.lagSmoothing(0);

    return () => { lenis?.destroy(); lenis = null; };
  });
</script>

{@render children()}

5.2 WebGLCanvas — single renderer, context-provided scene graph

<!-- $lib/webgl/WebGLCanvas.svelte -->
<script lang="ts">
  import { onMount, type Snippet } from 'svelte';
  import { provideWebGL } from './context';

  let { children, dpr = 1.5 }: { children: Snippet; dpr?: number } = $props();
  let canvas: HTMLCanvasElement;
  let ready = $state(false);

  onMount(async () => {
    const THREE = await import('three');       // code-split: three never hits content pages
    const renderer = new THREE.WebGLRenderer({ canvas, antialias: true, powerPreference: 'high-performance' });
    renderer.setPixelRatio(Math.min(devicePixelRatio, dpr));  // cap DPR: free FPS on retina

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(45, innerWidth / innerHeight, 0.1, 100);

    const onResize = () => {
      camera.aspect = innerWidth / innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(innerWidth, innerHeight);
    };
    onResize();
    addEventListener('resize', onResize);

    renderer.setAnimationLoop(() => renderer.render(scene, camera));
    provideWebGL({ renderer, scene, camera, canvas });
    ready = true;

    return () => {
      removeEventListener('resize', onResize);
      renderer.setAnimationLoop(null);
      renderer.dispose();
    };
  });
</script>

<canvas bind:this={canvas} class="fixed inset-0 -z-10" aria-hidden="true"></canvas>
{#if ready}{@render children()}{/if}

5.3 KineticText — scroll-driven split typography

<!-- $lib/components/KineticText.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';

  let {
    text,
    as = 'h2',
    scrub = true
  }: { text: string; as?: keyof HTMLElementTagNameMap; scrub?: boolean } = $props();

  let el: HTMLElement;

  onMount(async () => {
    if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    const { animate } = await import('animejs');
    const { splitText } = await import('animejs/text');
    const { onScroll } = await import('animejs');   // Scroll Observer [^12^]

    const words = splitText({ text, by: 'word', tag: 'span' });
    el.append(...words.nodes as Node[]);

    const anim = animate(words.nodes, {
      opacity: { to: 1 },
      translateY: { to: 0 },
      delay: (el, i) => i * 40,                     // stagger → swap for gwoka pattern (Part 3)
      ease: 'out(3)',
      duration: 600,
      autoplay: scrub
        ? onScroll({ target: el, enter: 'bottom-=10%', leave: 'top+=10%', sync: 0.5 })
        : true
    });
    return () => anim.revert();
  });
</script>

<svelte:element this={as} bind:this={el} aria-label={text} class="kinetic">{text}</svelte:element>

5.4 ParallaxLayer — multi-plane depth, CSS-first

<!-- $lib/components/ParallaxLayer.svelte -->
<script lang="ts">
  import { onMount, type Snippet } from 'svelte';
  let { depth = 0.3, children }: { depth?: number; children: Snippet } = $props();
  let el: HTMLElement;

  onMount(async () => {
    // Prefer native scroll-driven animations where supported (no JS per frame)
    if (CSS.supports('animation-timeline: view()')) {
      el.style.animationTimeline = 'view()';
      el.style.animationName = 'parallax-y';
      el.style.setProperty('--depth', String(depth));
      return;
    }
    const gsap = (await import('gsap')).default;
    const { ScrollTrigger } = await import('gsap/ScrollTrigger');
    gsap.registerPlugin(ScrollTrigger);
    const tween = gsap.to(el, {
      yPercent: -depth * 100,
      ease: 'none',
      scrollTrigger: { trigger: el, start: 'top bottom', end: 'bottom top', scrub: true }
    });
    return () => { tween.scrollTrigger?.kill(); tween.kill(); };
  });
</script>

<div bind:this={el} class="parallax-layer">{@render children()}</div>

<style>
  @keyframes parallax-y { to { transform: translateY(calc(var(--depth, 0.3) * -30%)); } }
</style>

5.5 CursorTracker — physics cursor + velocity uniform (Igloo pattern)

<!-- $lib/components/CursorTracker.svelte -->
<script lang="ts">
  import { onMount } from 'svelte';
  let dot: HTMLDivElement;

  onMount(async () => {
    if (matchMedia('(pointer: coarse)').matches) return;   // no cursor on touch
    const { createSpring } = await import('animejs');
    const spring = createSpring({ stiffness: 120, damping: 14 });

    let x = 0, y = 0, px = 0, py = 0;
    const onMove = (e: PointerEvent) => { x = e.clientX; y = e.clientY; };
    addEventListener('pointermove', onMove, { passive: true });

    let raf = 0;
    const tick = () => {
      const vx = x - px, vy = y - py;              // pointer velocity
      const speed = Math.min(Math.hypot(vx, vy) / 40, 1);
      dot.style.transform = `translate(${spring.solve(x, px)}px, ${spring.solve(y, py)}px) scale(${1 + speed * 0.6})`;
      // → also write (x, y, speed) into your WebGL uniforms here: cursor-as-light-source (Unseen pattern)
      px = x; py = y;
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    return () => { removeEventListener('pointermove', onMove); cancelAnimationFrame(raf); };
  });
</script>

<div bind:this={dot} class="cursor-dot" aria-hidden="true"></div>

5.6 PageTransition — GSAP route transitions (SvelteKit-safe)

<!-- +layout.svelte (site group) -->
<script lang="ts">
  import { onNavigate } from '$app/navigation';
  import { page } from '$app/state';

  onNavigate((nav) => {
    // Prefer native View Transitions where available (progressive enhancement)
    if (!document.startViewTransition) return;
    return new Promise((resolve) => {
      document.startViewTransition(async () => { resolve(); await nav.complete; });
    });
  });
</script>

{#key page.url.pathname}
  <main class="page"><slot /></main>
{/key}

<style>
  .page { view-transition-name: page; }
  ::view-transition-old(page) { animation: page-out 0.35s var(--ease-ka) both; }
  ::view-transition-new(page) { animation: page-in  0.45s var(--ease-ka) both; }
  @keyframes page-out { to { opacity: 0; transform: translateY(-2%); } }
  @keyframes page-in  { from { opacity: 0; transform: translateY(3%); } }
</style>

GSAP alternative for browsers without View Transitions: animate out in onNavigate's returned promise, animate in via afterNavigate. Keep durations in your CSS custom properties so both paths share the same motion tokens.

5.7 ScrollProgressBar — zétwal minimal progress

<!-- $lib/components/ScrollProgressBar.svelte -->
<script lang="ts">
  let progress = $state(0);
  const onscroll = () => {
    const max = document.documentElement.scrollHeight - innerHeight;
    progress = max > 0 ? scrollY / max : 0;
  };
</script>

<svelte:window {onscroll} />
<div class="progress" role="progressbar" aria-valuenow={Math.round(progress * 100)}
     aria-valuemin="0" aria-valuemax="100" aria-label="Progression de lecture">
  <span style:transform="scaleX({progress})"></span>
</div>

<style>
  .progress { position: fixed; inset: 0 0 auto; height: 3px; z-index: 50; }
  .progress span { display: block; height: 100%; transform-origin: left;
    background: linear-gradient(90deg, var(--lagune-phospho), var(--or-circuit)); }
</style>

5.8 Bonus — FlipbookCanvas (Apple pattern, connection-aware)

// $lib/actions/flipbook.ts — Svelte action
export function flipbook(canvas: HTMLCanvasElement, opts: { frames: (q: 'full'|'lite') => string[]; total: number }) {
  const conn = (navigator as any).connection;
  const quality = conn?.effectiveType === '4g' && !conn?.saveData ? 'full' : 'lite';
  const urls = opts.frames(quality);
  if (conn?.effectiveType === 'slow-2g' || conn?.effectiveType === '2g' || conn?.saveData) {
    // Apple doctrine: single fallback image, no sequence [^19^]
    const img = new Image(); img.src = urls[0];
    img.onload = () => canvas.getContext('2d')?.drawImage(img, 0, 0);
    return {};
  }
  const imgs = urls.map((u) => { const i = new Image(); i.src = u; return i; });
  const ctx = canvas.getContext('2d')!;
  const draw = (p: number) => {
    const f = Math.min(urls.length - 1, Math.floor(p * urls.length));
    if (imgs[f]?.complete) ctx.drawImage(imgs[f], 0, 0, canvas.width, canvas.height);
  };
  const onscroll = () => {
    const max = document.documentElement.scrollHeight - innerHeight;
    requestAnimationFrame(() => draw(max > 0 ? scrollY / max : 0));
  };
  addEventListener('scroll', onscroll, { passive: true });
  return { destroy: () => removeEventListener('scroll', onscroll) };
}

6. Svelte-Specific Translations (React/Next.js → Svelte idioms)

React pattern (seen on these sites) Svelte 5 idiom
useRef + useEffect(() => {...}, []) for GSAP init $effect(() => { /* init */; return () => cleanup }) — or better, a Svelte action use:gsapThing
useContext(WebGLContext) setContext/getContext with a Symbol key (§2.2)
useState for animation params $state rune; params read inside $effect re-run the tween — guard with gsap.quickTo or quickSetter for per-frame writes
Derived uniforms (useMemo) $derived(() => computeUniforms(pointer, scroll)) — recalculates only on dependency change
R3F <Canvas> + hooks Threlte for declarative scenes; raw Three in onMount for shader-heavy work (Noomo avoided R3F for flexibility 22 — same logic applies)
framer-motion layout animations Svelte built-in flip (from svelte/animate) + crossfade (from svelte/transition) — free, SSR-safe
Zustand/Redux for UI state $state in a .svelte.ts module — a class with rune fields is your store

Runes vs stores for animation state: stores still work and are fine for cross-app state; but animation state should live in $state/$derived inside components or .svelte.ts modules — runes give finer-grained reactivity (no subscriber fan-out per frame). Critical rule: never write per-frame values (scrollY, pointer) into reactive state that drives DOM — write them to refs/plain variables and flush via rAF, or you'll re-render at 60 Hz.

GSAP + runes compatibility: GSAP mutates the DOM directly — Svelte doesn't care as long as GSAP's targets aren't nodes Svelte also patches (avoid tweening attributes Svelte controls via bindings). Wrap GSAP targets in {@html}-free static markup or bind via bind:this, init in $effect, kill in the cleanup function. Anime.js v4's createScope({ root }) + scope.revert() is the same lifecycle shape and tree-shakes better 4 .


7. Accessibility & Fallbacks

  1. Screen readers in immersive sites: canvas is aria-hidden; a semantic DOM mirror carries all content (Apple pattern 29 ). If you render UI text in WebGL (Igloo), ship a visually-hidden parallel DOM (sr-only list of the same links/labels).
  2. Reduced motion: one global gate — matchMedia('(prefers-reduced-motion: reduce)') checked in SmoothScrollProvider (no Lenis), KineticText (no split/scrub), ParallaxLayer (static), flipbook (poster frame). Implement it once, at the provider level, not per component.
  3. Graceful degradation ladder (the Gwada ladder):
    • navigator.connection.saveData or effectiveType ≤ 3g → static images, no autoplay video, no sequence preloading 29
    • deviceMemory ≤ 4 or WebGL context creation fails → DOM-effects-only mode (Zentry proves DOM-only can still win awards 11 )
    • <noscript> / JS-disabled → SSR content is complete and readable (this is why SSR matters)
  4. Focus management: route transitions must move focus to the new page's <h1>; scroll-jacking (Lenis) must never break keyboard scrolling — Lenis preserves native scroll, which is why it's the right engine choice.
  5. Bilingual a11y: lang attributes per text node (fr / gcf) — screen readers switch voices; crucial for Kréyòl content.

8. Tooling Recommendations

Essential packages (open-source first, per your doctrine)

{
  "dependencies": {
    "lenis": "^1.3",            // smooth scroll — the award-site standard [^20^][^27^]
    "gsap": "^3.13",            // timelines, ScrollTrigger, ticker
    "animejs": "^4.2",          // modular springs/stagger/splitText [^5^]
    "three": "^0.1xx",          // WebGL — dynamic-import only
    "@threlte/core": "^8",      // optional: declarative Three in Svelte
    "troika-three-text": "^0.5" // SDF text in WebGL (Igloo pattern, if needed)
  },
  "devDependencies": {
    "@gltf-transform/cli": "^4",// meshopt/KTX2 pipeline (§4.2)
    "vite-imagetools": "^7",    // responsive AVIF/WebP at build
    "sharp": "^0.33"
  }
}
  • Vite plugins: vite-imagetools (build-time responsive images), vite-plugin-pwa (offline mode = real resilience on flaky 4G, plus an installable PWA for AKILPA), basic manualChunks splitting three into its own async chunk.
  • HMR for WebGL: Vite HMR reloads Svelte components but not your GL state — keep scene setup idempotent (init/dispose symmetric in $effect), store debug params in URL hash so a reload restores your camera/scrub position. Shader files as ?raw imports hot-reload cleanly.
  • Hosting (≤50 €/mo, actually near 0 €): Cloudflare Pages + R2 — the exact Kriss.ai architecture 10 ; free tier absorbs heavy media via edge CDN. Netlify/Vercel free tiers work too; avoid anything Node-server-based (Immersive Garden's Strapi 7 is out of budget — use a headless Git-based CMS or plain Markdown in-repo).

PART 3 — CYBER-MAWONAJ ADAPTATION

How the 15-site DNA translates for a Caribbean, sovereign, 4G-first aesthetic. This is not "apply a tropical skin" — it's re-deriving each decision from the local context.

Color system (CSS tokens, oklch for perceptual control)

:root {
  --lagune-phospho: oklch(72% 0.13 210);  /* phosphorescent lagoon blue — primary accent */
  --roche-volcan:   oklch(18% 0.02 260);  /* volcanic rock black — dominant ground */
  --corail:         oklch(70% 0.16 25);   /* coral pink — secondary accent */
  --or-circuit:     oklch(80% 0.14 90);   /* circuit gold — data/tech highlights */
  --foret-neon:     oklch(55% 0.15 155);  /* deep forest green, used with neon edge-glow */
  --terre-rouge-a:  oklch(45% 0.12 40);   /* terre rouge gradient stop A */
  --terre-rouge-b:  oklch(30% 0.09 55);   /* terre rouge gradient stop B — use for section grounds */
}

Dark-mode-first (--roche-volcan ground) = OLED battery saving + the bioluminescence aesthetic for free. The arc-en-ciel / rainbow-serpent motif belongs in gradients and particle hues (velocity-shifted color, Igloo pattern 14 ) — never as static rainbow fills.

Cultural signifiers → concrete UI patterns

Signifier Pattern (source site) Implementation
Lambi shell UI motif: shell-spiral as scroll progress, loader, section dividers SVG spiral stroke-dashoffset scrub (createDrawable, animejs/svg 4 ); KTX2 shell texture for WebGL hero
Zétwal (stars) Navigation: constellation nav where sections are stars DOM + SVG lines; hover = star brightens + label reveals; light-years cheaper than a WebGL starfield
Dollhouse créole Kriss.ai spatial IA 10 AKILPA sections as case à ka / marché / karbay / plage rooms — isometric DOM illustration, no WebGL needed
Terre rouge Section backgrounds gradient Pure CSS, zero cost
Mawon/maroon resistance Visual language: glitch-free, hand-made texture; KPR's community-shaped tableaux 16 UGC/content layers: community-submitted photos as parallax planes; "Backstage" section documenting the process (Immersive Garden pattern 7 ) = transparency as sovereignty

Typography (FR/KRÉ bilingual, low-res safe)

  • Weights: ≥ 400 body, ≥ 600 display — thin weights die on low-DPI screens (your constraint is correct).
  • Suggested open fonts: Space Grotesk (display, tech-caribbean tension) + Inter or Atkinson Hyperlegible (body, legibility-first, open license). Atkinson is the sovereignty-aligned choice: designed for low-vision readers.
  • Kinetic type via splitText on words, not characters, for Kréyòl — character-splitting can break apostrophe-heavy words (mwen, tèt'w) visually and for screen readers. Keep aria-label with the intact string (component §5.3 does this).
  • Language switch as animation event (Nudot pattern): mask-swap lines in place.

Motion design — gwoka cadences as easing/timing tokens

Award sites ship custom ease curves; yours can carry rhythm. Practical translation:

:root {
  /* ka/belair-inspired: strong downbeat, syncopated release */
  --ease-ka:     cubic-bezier(0.22, 1, 0.36, 1);   /* downbeat: fast attack, long settle */
  --ease-syncope: cubic-bezier(0.65, 0, 0.35, 1);  /* off-beat: symmetric, urgent */
  --dur-tanbou:  120ms;   /* sixteenth @ ~125 BPM — micro-interactions */
  --dur-mesure:  480ms;   /* one bar — entrances */
  --dur-phrase:  960ms;   /* two bars — page transitions */
}

Stagger patterns: instead of linear i * 40ms, use syncopated stagger [0, 120, 240, 360, 480, 600, 720, 840] → remap to [0, 120, 300, 360, 600, 660, 900, 960] (3+3+2 feel). Subtle, but rhythm is identity.

The Gwada connectivity doctrine (non-negotiables)

  1. Connection-aware everything — flipbook component §5.8 is the reference implementation 29 .
  2. DOM-first effects — Zentry is your patron saint here 11 .
  3. PWA with offline shell — an association site that works in a dead zone is a political statement (souveraineté numérique).
  4. Test hardware: a ~150 € Android on real 4G in Gwada, not Lighthouse throttling.
  5. Edge hosting: Cloudflare Pages/R2 10 — points of presence in the Americas, near-zero cost, aligns with the 50 €/mo ceiling (realistically: < 5 €/mo).

PART 4 — COMPARISON MATRIX

# Site Visual Motion Tech UX Stealable pattern
1 unseen.co Volumetric light, dark bloom Inertial, particle-driven Three.js 2 Scroll-journey portfolio Cursor-as-light uniform
2 animejs.com Lab-instrument dark, kinetic type Springs, staggers, scroll-observer Three hero + Anime.js v4 modules 4 3 Interactive docs createScope per component
3 immersive-g.com Bas-relief minimalism Ceremonial glide Nuxt, Three, GSAP, Lenis, Strapi, KTX pipeline 7 One-click access + Backstage Backstage process section
4 davidwhyte.com/experience Watercolor organic Fluid sim, baked-noise reveals Nuxt, Three, GSAP, Lenis, WP 9 Slow contemplative tempo Bake generative noise offline
5 kriss.ai/aftercare 70s warm dollhouse Room-to-room camera WebGL/Blender, Cloudflare Pages+R2 10 Spatial metaphor IA Dollhouse IA (créole rooms)
6 zentry.com Bold saturated portals Motion-system-first Nuxt, pure DOM — no WebGL 11 Portal reveals + sound DOM-only 3D portal masks
7 igloo.inc Procedural ice, chromatic frost Velocity particles, SDF glitch Three + Svelte + GSAP 14 3-section scroll journey Velocity-reactive particles
8 kprverse.com Concept-art tableaux Click-and-hold layers Resn (Nuxt-class) 16 Lore gating, terminal loader Click-hold reveal layer
9 hape.io Fashion editorial Scroll-scrubbed walk + music sync Custom OGL micro-framework 19 Single-idea focus Scroll-scrubbed animation clip
10 labs.noomoagency.com Glass jellyfish dream Baked camera playback Three + GSAP, no R3F, Blender-baked 22 Public R&D hub Two-Empty baked camera rig
11 noomoagency.com Disciplined glassmorphism Per-element hover craft Nuxt 3 full-stack, Three, GSAP 24 Classic IA, flawless transitions Budgeted hover craft (5 elements)
12 nudot.com.tw Bilingual kinetic type Character reveals, hover previews DOM/GSAP-class (inference) Bilingual as feature Language-switch as animation
13 375.studio Two-color discipline Systematic micro-motion DOM-first (inference) Every state designed Designed 404/empty states
14 ten.375.studio Interactive comic Panel scrubbing, mouse trail DOM/SVG (inference) Chaptered narrative Chaptered scroll-comic
15 apple.com/airpods-pro Photographic black Scroll flipbook, master timeline Canvas 2D image sequence 29 30 Desire before specs Connection-aware flipbook

= highest ROI for Cyber-mawonaj constraints (4G, low-end, sovereignty).


Sources


  1. https://www.awwwards.com/directory/agency-studio/ — Unseen Studio directory stats (35 SOTD) ↩︎

  2. https://x.com/uns__nstudio — Unseen Studio: rebrand from GC, volumetric studies, particle sims, three.js tags ↩︎

  3. https://www.reddit.com/r/webdev/comments/1jqmqkn/ — r/webdev on animejs.com v4 site (Three.js hero) ↩︎

  4. https://github.com/juliangarnier/anime/issues/1105 — Anime.js v4 LLM guiding file (API modules, createScope, splitText) ↩︎

  5. https://animejs.com/ — Anime.js feature docs (Scroll Observer, stagger, SVG toolset) ↩︎

  6. https://www.awwwards.com/immersivegarden/ — Immersive Garden profile (Studio of the Year ×3) ↩︎

  7. https://www.awwwards.com/case-study-immersive-gardens-new-website.html — KTX compression, channel packing, gltf-transform; Nuxt/Three/GSAP/Lenis/Strapi/Vercel ↩︎

  8. https://www.awwwards.com/sites/david-whyte-experience — David Whyte Experience SOTD Dec 31 2024 ↩︎

  9. https://www.awwwards.com/case-study-david-whyte-experience-by-immersive-garden.html — fluid-sim atlas, baked noise, full stack (Nuxt/Three/GSAP/Lenis/WP/Vercel) ↩︎

  10. https://www.awwwards.com/case-study-ai-with-a-human-touch-the-new-face-of-kriss-ai.html — Kriss.ai dollhouse concept; Cloudflare Pages + R2 ↩︎

  11. https://www.awwwards.com/zentry-case-study.html — Zentry case study (Resn): Nuxt/Vue/Vite, DOM-only 3D portal masks, no WebGL ↩︎

  12. https://www.awwwards.com/sites/igloo-inc — Igloo Inc, Awwwards SOTD Jul 23 2024 ↩︎

  13. https://www.awwwards.com/igloo-inc-case-study.html — Igloo Inc case study (Abeto × Bureaux) ↩︎

  14. https://www.webgpu.com/showcase/igloo-inc-procedural-crystals/ — Igloo Inc: Crystal Growth Algorithms, Shader-Driven UI, and Volume Data (Feb 2026) ↩︎

  15. https://www.awwwards.com/sites/kpr — KPR SOTD Dec 26 2022 ↩︎

  16. https://www.awwwards.com/kpr-by-resn-wins-sotm.html — KPR by Resn SOTM: click-and-hold layers, tableaux, 3D+2D mix ↩︎

  17. https://kprverse.com/ — KPR live site: terminal loader strings, device gating messages ↩︎

  18. https://www.awwwards.com/sites/hape — HAPE SOTD Apr 27 2022 ↩︎

  19. https://www.deptagency.com/case/creating-a-3d-nft-walking-hape/ — HAPE: custom OGL micro-framework, PBR, skinning; 4-week build ↩︎

  20. https://dogstudio.co/cases/hape-prime/ — HAPE walk concept, scroll camera, soundtrack sync ↩︎

  21. https://noomoagency.com/ — Noomo Agency honors list (WOTY, Labs awards) ↩︎

  22. https://www.awwwards.com/noomo-labs-a-hub-for-cutting-edge-immersive-experiences.html — Noomo Labs behind the scenes: Three+GSAP, no R3F, Blender-baked, two-Empty camera ↩︎

  23. https://www.webgpu.com/showcase/noomo-3d-storytelling-threejs/ — Noomo 3D storytelling site write-up ↩︎

  24. https://medium.com/@noomo-agency/noomo-agency-website-of-the-year-winner-on-awwwards-aad757327994 — Noomo: Nuxt 3, Three.js, GSAP ↩︎

  25. https://www.awwwards.com/sites/noomo-agency — Noomo Agency SOTD Sep 21 2023, elements list ↩︎

  26. https://www.awwwards.com/Studio375/ — Studio375 profile & awards ↩︎

  27. https://www.awwwards.com/sites/studio375 — Studio375 HM (2023): elements incl. animated 404 ↩︎

  28. https://www.awwwards.com/sites/ten-years-away — Ten Years Away, Awwwards SOTD Jun 26 2026 ↩︎

  29. https://css-tricks.com/lets-make-one-of-those-fancy-scrolling-animations-used-on-apple-product-pages/ — Apple flipbook technique + slow-connection fallback ↩︎

  30. https://gsap.com/community/forums/topic/25188-airpods-image-sequence-animation-using-scrolltrigger/ — master-timeline percentage technique ↩︎