Skip to main content

En bref

Les assets « lourds » d’une scène (modèles .glb, textures, images de template, vidéos, PDF) ne sont pas embarqués en dur dans l’app open. Ils sont servis depuis un CDN Cloudflare (R2 public), résolus au runtime par le helper asset() de @wrappy/core. Deux familles d’assets, à ne pas confondre : Cette page couvre la première famille. L’UGC par invitation passe par le module storage de l’API et le champ attachments du payload.

Le schéma de versionning

L’URL d’un asset template suit toujours cette forme :
  • namespace = la scène (ou le composant partagé) propriétaire de l’asset. C’est le slug de la scène : fete-des-laurens, web-form, 3d-book, gift-physics
  • version = v1, v2versionnée par namespace (voir plus bas). Chaque scène évolue à son rythme.
  • chemin = le chemin de l’asset dans son dossier (/models/x.glb, /images/ticket.png).
Exemple concret :
Le versionning est par namespace, pas global. Changer un asset de web-form bumpe web-form en v2 sans toucher fete-des-laurens, qui reste en v1.

Pourquoi versionner

Les dossiers publiés sont immuables : on ne réécrit jamais un vN déjà en ligne. Une invitation déjà envoyée a été buildée avec VITE_ASSET_BASE_URL pointant sur une version donnée — si on écrasait les assets, elle changerait d’apparence après coup. Une révision d’asset = nouveau dossier v2, l’ancien continue de vivre.

Comment ça marche

Le helper asset()

packages/core/src/lib/assets.ts :
  • VITE_ASSET_BASE_URL = la racine CDN, sans version (ex: https://cdn.wrappy.app/templates/scenes). La version n’est pas dans l’env var — elle vit dans VERSIONS.
  • VERSIONS = la table qui fixe la version courante de chaque namespace. C’est le seul endroit à toucher pour bumper.

Dev vs prod : même structure

En dev, VITE_ASSET_BASE_URL est vide → CDN_ROOT retombe sur /templates/scenes, servi statiquement par Vite depuis apps/open/public/. Le dossier public/ est organisé exactement comme le CDN : dev et prod résolvent le même chemin, aucune divergence.

Développer une scène : utiliser asset()

1

Ranger les fichiers dans public/

Place tes assets sous apps/open/public/templates/scenes/<ns>/v1/…, en gardant une arborescence lisible (/models, /images, /videos).
2

Déclarer le namespace dans VERSIONS

Ajoute une entrée dans VERSIONS (packages/core/src/lib/assets.ts) :
Si le namespace est absent de VERSIONS, asset() retombe sur v1 par défaut — mais déclare-le explicitement pour pouvoir le bumper plus tard.
3

Référencer via asset() dans la scène

Ne mets jamais de chemin d’asset en dur. Passe toujours par asset(namespace, path) :
asset prend deux arguments. ["/a.png"].map(asset) ne marche pas (.map passe l’index en 2ᵉ argument) — utilise .map((p) => asset("ma-scene", p)).
4

Tester en dev

bun run dev et vérifie que l’asset charge (onglet Network → 200 sur /templates/scenes/ma-scene/v1/…). Comme public/ reflète le CDN, ce qui marche en dev marchera en prod.

Assets partagés entre scènes

Si un composant est réutilisé par plusieurs scènes (ex: le livre 3D 3DBook, embarqué par fete-des-laurens et web-form), ses assets vivent sous son propre namespace (3d-book), pas dupliqués sous chaque scène :

Bumper un asset (nouvelle version)

Quand tu modifies un asset déjà publié en prod :
1

Créer le nouveau dossier de version

Copie les assets du namespace sous …/<ns>/v2/… dans public/templates/scenes/. Ne touche pas au dossier v1.
2

Bumper VERSIONS

Tous les asset("ma-scene", …) pointent maintenant sur v2. Aucun autre changement de code.
3

Publier sur le CDN

Voir la section suivante. Le v1 reste en ligne pour les invitations déjà buildées.

Publier sur le CDN

Le script scripts/upload-scene-assets.sh est un miroir récursif de public/templates/scenes/ vers le bucket R2 public :
Il pousse chaque fichier sous la même clé (templates/scenes/<ns>/<version>/…) via wrangler. Comme les dossiers de version sont immuables, republier ne réécrit que ce qui a changé (les nouveaux vN). Côté build de open, poser :
VITE_ASSET_BASE_URL est une variable build-time de Vite (préfixe VITE_), injectée via un ARG/ENV dans apps/open/Dockerfile. Elle est figée au build.

Ce qui reste hors CDN

Les petits assets non liés à une scène restent servis par l’app depuis public/ (à la racine, pas sous templates/scenes/) : logos, favicon, manifest.json, sons courts (page-flip.mp3), image OG de fallback. Trop petits pour justifier le détour CDN.

Récap

  • Un asset de scène = asset(namespace, path), jamais un chemin en dur.
  • namespace = slug de la scène ; path = chemin dans son dossier.
  • La version vit dans VERSIONS (packages/core/src/lib/assets.ts), par namespace.
  • public/templates/scenes/ reflète le CDN à l’identique → dev == prod.
  • Bump = nouveau dossier vN + mise à jour de VERSIONS, jamais d’écrasement.
  • Publication = scripts/upload-scene-assets.sh.