Un guide pratique : créez un annuaire d’aéroports internationalisé sur Profound CMS — une route paramétrique qui génère une page pour chaque aéroport, en 35 langues.
Créez un véritable annuaire d’aéroports internationalisé sur Profound CMS : un motif d’URL qui génère une page pour chaque aéroport, en 35 langues. Vous écrivez le code Next.js et construisez la structure du CMS à la main ; Claude Code (via le Profound MCP) s’occupe de trois tâches — générer les données des aéroports, connecter un système de design et générer les quatre composants React. Trois parties : Configuration, Construction, Production.
Regardez la vidéo de présentation complète.
/{language}/{airport_code}.cms-renderer.curl -fsSL https://bun.sh/install | bashgh) connecté et un compte Vercel relié à GitHub.language) sont fournis par défaut.cms-renderer avec une clé API de niveau lecture.État final : ~50 aéroports dans le CMS, l’application connectée pour les lire, et le système de design en place.
Inscrivez-vous sur Profound (authentification WorkOS) et créez un site nommé airports. Copiez deux éléments : l’ID du site (le UUID dans l’URL d’administration) et une clé API de niveau lecture depuis Deployments → Create API key. L’application ne fait que lire, une clé de lecture suffit donc.
bunx create-profound-next airports
cd airports
Ajoutez vos identifiants à .env.local :
PROFOUND_API_KEY=<your read key>
NEXT_PUBLIC_PROFOUND_WEBSITE_ID=<your website id>
NEXT_PUBLIC_CMS_API_URL=https://cms.dev.tryprofound.com
NEXT_PUBLIC_BUNNY_CDN_URL=https://cms-profound.b-cdn.net
Exécutez bun dev et ouvrez localhost:3000 pour confirmer la connexion.
airportDans l’admin, allez à Components → Create new component et nommez-le airport. Ajoutez six champs : code, name, city, country (Text) et latitude, longitude (Number). Marquez code comme champ Route Slug et définissez le statut sur Active. Laissez tous les champs facultatifs ; n’ajoutez aucune étiquette UI Element.
Le composant airport — six champs, avec code défini comme Route Slug.
bun run generate-schemas
Cela écrit airportSchema (Zod) et Airport (type) dans generated/cms-schemas.ts, et confirme que vos identifiants fonctionnent.
Connectez le MCP et authentifiez-vous :
claude mcp add --transport http Profound http://107.21.107.99:8081/mcp
Le serveur s’authentifie via OAuth (WorkOS). Dans Claude Code, exécutez /mcp, choisissez Profound et terminez la connexion dans votre navigateur — Claude Code vous y invite également automatiquement lors du premier appel à un outil Profound. Une fois que /mcp affiche Profound comme connected, demandez à Claude :
Génère cinquante aéroports réels — codes IATA valides, noms, villes, pays et coordonnées. Enregistre-les en JSON dans un dossier
data, valide-les par rapport à notre composant airport, puis crée chacun comme document publié via le Profound MCP, en parallèle.
Ouvrez airport → Variants pour confirmer ~50 aéroports publiés. L’application lit avec la clé API ; le MCP écrit avec sa propre session WorkOS.
Environ 50 aéroports, initialisés comme variantes publiées.
Le squelette est livré sans style. Placez un fichier DESIGN.md (un bloc @theme Tailwind v4 plus des tokens) à la racine du projet — le vôtre, ou téléchargez-en un sur refero.design. Ensuite, demandez à Claude :
Lis DESIGN.md. Configure Tailwind v4 et connecte le thème et les polices. Utilise
next/fontpour les polices, pas d’import Google au runtime. Style uniquement — pas de pages ni de composants pour l’instant.
Vérifiez que src/app/globals.css contient @import "tailwindcss"; ainsi que le bloc @theme, et que localhost:3000 affiche les tokens.
Construisez la couche de rendu : les éléments d’interface, les composants React, la route, les liaisons CEL et la traduction.
Dans l’admin, Create new component quatre fois (sans Route Slug). Pour chacun, ajoutez les champs en Text sauf mention contraire, définissez le statut sur Active et ajoutez l’étiquette UI Element dans Settings → Tags :
nav → brandheadline → title, subtitlebody → code, city, country, latitude (Number), longitude (Number)footer → textbody.latitude et body.longitude doivent être en Number pour correspondre au composant airport.
Chaque élément d’interface est son propre composant — ici body, défini sur Active avec l’étiquette UI Element.
Les quatre éléments d’interface aux côtés du composant airport.
bun run generate-schemas
Demandez à Claude :
Crée quatre composants React — nav, headline, body, footer — dans
components/. Chacun doit accepter une prop uniquecontenttypée commeBlockComponentProps<T>depuiscms-renderer/lib/types, oùTest le type généré de l’élément, et lire ses champs surcontent. Enregistre les quatre dans le registre de la route catch-all par leur nom de composant. Stylise-les avec notre système de design, mais comme nos propres composants — ne copie pas la mise en page du site source. Nav : marque à gauche. Headline : nom de l’aéroport avec un sous-titrecode · ville, pays. Body : panneau de détails avec code, ville, pays et coordonnées. Footer : une ligne statique. Mise en page et style uniquement.
Claude crée les quatre composants et complète le registre dans src/app/[...slug]/page.tsx :
const registry = { nav: Nav, headline: Headline, body: Body, footer: Footer };
Deux règles : chaque composant lit ses champs sur content (pas comme props séparées), et les clés du registre doivent correspondre exactement aux noms des composants dans le CMS — sinon le rendu reste vide.
Dans l’admin, allez à Pages → Create page et définissez le motif /{airport_code}. Sous Dynamic Segment Mappings, mappez airport_code → le composant airport, champ slug code. Enregistrez — vous arrivez dans le Page Builder. Vérifiez que /JFK fonctionne.
Ajout d’un élément d’interface à la page depuis l’onglet Custom.
Les quatre éléments d’interface ajoutés à la liaison JFK dans le Page Builder.
Choisissez la liaison JFK → Add UI Element → onglet Custom → ajoutez nav, headline, body, footer dans cet ordre. Profound réplique cet ensemble sur chaque liaison d’aéroport.
Remplissez chaque champ. Valeurs statiques (marque de la nav, texte du pied de page) : saisissez-les directement. Valeurs dynamiques : passez en mode dynamique et écrivez du CEL. La recherche partagée est documents.get("airport", meta.params.airport_code).
| Champ | Valeur CEL |
|---|---|
headline.title | documents.get("airport", meta.params.airport_code).name |
headline.subtitle | documents.get("airport", meta.params.airport_code).code + " · " + documents.get("airport", meta.params.airport_code).city + ", " + documents.get("airport", meta.params.airport_code).country |
body.code / body.city / body.country | documents.get("airport", meta.params.airport_code).<field> |
body.latitude / body.longitude | documents.get("airport", meta.params.airport_code).latitude (et .longitude) |
nav.brand, footer.text | chaînes statiques |
Publiez la page (en haut à droite).
Ouvrez localhost:3000/JFK, puis /SFO, /LAX — même modèle, aéroport différent.
La page finale affichant les données de JFK, en anglais.
Traduisez d’abord les composants. Dans l’admin, ouvrez chaque composant (n’importe lequel — il n’a pas besoin d’être un élément d’interface) et cliquez sur Translate → Submit. Profound traduit son contenu dans les 35 langues en une seule fois, valeurs statiques incluses. Faites-le avant de modifier la route ou de toucher au CEL.
Translate → Submit envoie un composant dans les 35 langues d’un coup.
Ajoutez la dimension de langue. Dans Pages, modifiez le motif en /{language}/{airport_code}. Ajoutez un Dynamic Segment Mapping pour language → le composant système intégré language, champ slug code. Enregistrez et vérifiez que /en/JFK fonctionne.
Ajout du segment {language} à la route.
Orientez chaque champ traduisible vers la récupération traduite. Internationaliser la page signifie basculer tous les champs dépendants de la langue — pas seulement le titre — de documents.get(...) à documents.translated("airport", meta.params.airport_code, meta.params.language) :
| Champ | CEL traduit |
|---|---|
headline.title | documents.translated("airport", meta.params.airport_code, meta.params.language).name |
headline.subtitle | documents.get("airport", meta.params.airport_code).code + " · " + documents.translated("airport", meta.params.airport_code, meta.params.language).city + ", " + documents.translated("airport", meta.params.airport_code, meta.params.language).country |
body.city / body.country | documents.translated("airport", meta.params.airport_code, meta.params.language).city (et .country) |
Laissez le code IATA et les coordonnées sur documents.get — ils sont identiques dans chaque langue. nav.brand et footer.text sont déjà couverts par la traduction du composant à l’étape 1.
Une fois ces trois actions terminées, /fr/SFO, /de/SFO, etc. s’affichent entièrement traduits.
Poussez sur GitHub :
git init
git add -A
git commit -m "Airport directory"
gh repo create airports --public --source=. --push
Importez dans Vercel : Add New → Project → importez le dépôt airports. Ajoutez les variables d’environnement — PROFOUND_API_KEY, NEXT_PUBLIC_PROFOUND_WEBSITE_ID, NEXT_PUBLIC_CMS_API_URL, et éventuellement NEXT_PUBLIC_BUNNY_CDN_URL — puis Deploy. Visitez /en/JFK et /fr/SFO. Chaque futur git push redéploie.
Les deux sont fournis avec le squelette.
<Refresher> dans layout.tsx met à jour la page que vous prévisualisez lorsque vous modifiez et enregistrez dans l’admin — sans redéploiement.?edit_mode=true à n’importe quelle URL (par ex. …/en/JFK?edit_mode=true) pour afficher les superpositions d’édition. Les visiteurs publics voient toujours la page propre.?edit_mode=true affiche l’éditeur en superposition sur la page en production.
Cinquante aéroports, 35 langues, en production — décrits une seule fois et alimentés par les données : une route, quatre composants React et une poignée de liaisons CEL. Le CMS conserve le contenu, votre code le rend, et CEL fait le lien.