Désormais avec création de pages par IA via le serveur MCP

Médias

Images et fichiers vivent dans la médiathèque de l'espace de travail. Comment les blocs les référencent, pourquoi chaque envoi obtient sa propre URL, et ce que cela implique au remplacement.

Les médias sont au niveau de l'espace de travail, pas de la page. Une bibliothèque, organisée en dossiers, partagée par toutes les pages et tous les blocs.

Le champ média

Un bloc atteint un asset via fields.media :

export const imageProps = {
  src: fields.media({ label: "Image", required: true }),
  alt: fields.text({ label: "Alt text" }),
};

La valeur stockée est une chaîne d'URL, ni un identifiant ni un objet. Votre composant la reçoit prête à l'emploi :

function ImageBlock({ content }) {
  if (!content.src) return null;
  return <img src={content.src} alt={content.alt ?? ""} />;
}

Comme la valeur est une simple URL, un champ média ne coûte rien au rendu : pas de recherche, pas d'étape de résolution, pas d'état où l'image charge encore.

Chaque envoi obtient sa propre URL

Les assets envoyés sont servis depuis un hôte CDN, avec un hash dans le chemin :

https://assets.cmssy.io/{workspaceId}/78aa0167-cmssy-og-default.png

Ce hash est propre à chaque envoi. C'est ce qui rend les assets immuables et cachables sans limite - mais cela a une conséquence qu'on découvre souvent à la dure :

Téléverser un remplacement ne met pas à jour les blocs qui pointent vers l'ancien fichier. Un nouvel envoi est une nouvelle URL ; les blocs existants gardent l'ancienne et continuent d'afficher l'ancienne image. Si vous avez changé un logo et que le site montre encore le précédent, rien n'est mal mis en cache : les blocs pointent simplement là où ils ont toujours pointé.

Il n'y a pas de remplacement sur place : les outils médias sont lister, envoyer et déplacer, donc un nouveau fichier signifie toujours une nouvelle URL. Le remède est de re-pointer les blocs - un chercher-remplacer sur le contenu des blocs, ce que le serveur MCP fait bien.

La conséquence pratique mérite d'être anticipée. Un asset référencé par de nombreuses pages - un logo, une image OG par défaut - se remplace à moindre coût s'il passe par la configuration du site ou un bloc unique, plutôt que d'être collé à vingt endroits.

Dossiers

Les dossiers forment un arbre plat avec un parentId. Ils organisent la bibliothèque pour les humains ; ils ne font pas partie de l'URL, déplacer un asset ne casse donc rien.

Via MCP vous pouvez lister, créer, renommer, supprimer et déplacer - ce qui rend une grande réorganisation scriptable plutôt qu'un après-midi de glisser-déposer.

Images Next.js

Les assets viennent d'une autre origine que votre application : next/image les refusera tant que l'hôte n'est pas autorisé :

// next.config.mjs
const nextConfig = {
  images: {
    remotePatterns: [
      { protocol: "https", hostname: "assets.cmssy.io" },
    ],
  },
};

Un joker hostname: "**" fonctionne et c'est ce qu'utilise l'application de référence, mais il laisse passer n'importe quel hôte HTTPS dans votre optimiseur d'images. Nommer l'hôte des assets est le choix plus serré, et coûte une ligne.

Le texte alternatif est du contenu

Associez chaque fields.media à un champ texte pour l'alt, et laissez les éditeurs le remplir. L'alt décrit ce que l'image signifie dans ce contexte - la même photo demande un alt différent dans une étude de cas et dans un mur de logos. Ce ne peut pas être une propriété du fichier : voilà pourquoi cela appartient au bloc et non à la bibliothèque.

Étapes suivantes