Um walkthrough prático: construa um diretório de aeroportos internacionalizado no Profound CMS — uma rota paramétrica que renderiza uma página para cada aeroporto, em 35 idiomas.
Construa um diretório de aeroportos real e internacionalizado no Profound CMS: um padrão de URL que renderiza uma página para cada aeroporto, em 35 idiomas. Você escreve o código Next.js e monta a estrutura do CMS manualmente; o Claude Code (via o Profound MCP) cuida de três tarefas — gerar os dados dos aeroportos, conectar um sistema de design e gerar os quatro componentes React. Três partes: Configuração, Construção, Produção.
Assista ao vídeo com o walkthrough completo.
/{language}/{airport_code}.cms-renderer.curl -fsSL https://bun.sh/install | bashgh) autenticado e uma conta na Vercel vinculada ao GitHub.language) já vêm prontos.cms-renderer com uma chave de API de nível de leitura.Estado final: cerca de 50 aeroportos no CMS, o app conectado para lê-los e o sistema de design instalado.
Cadastre-se na Profound (autenticação WorkOS) e crie um site chamado airports. Copie duas coisas: o ID do site (o UUID na URL do admin) e uma chave de API de leitura em Deployments → Create API key. O app só faz leitura, então uma chave de leitura basta.
bunx create-profound-next airports
cd airports
Adicione suas credenciais em .env.local:
PROFOUND_API_KEY=<sua chave de leitura>
NEXT_PUBLIC_PROFOUND_WEBSITE_ID=<o ID do seu site>
NEXT_PUBLIC_CMS_API_URL=https://cms.dev.tryprofound.com
NEXT_PUBLIC_BUNNY_CDN_URL=https://cms-profound.b-cdn.net
Execute bun dev e abra localhost:3000 para confirmar a conexão.
airportNo admin, vá para Components → Create new component e nomeie-o airport. Adicione seis campos: code, name, city, country (Text) e latitude, longitude (Number). Marque code como o campo Route Slug e defina o status como Active. Deixe todos os campos opcionais; não adicione nenhuma tag de UI Element.
O componente airport — seis campos, com code definido como Route Slug.
bun run generate-schemas
Isso grava airportSchema (Zod) e Airport (tipo) em generated/cms-schemas.ts, e confirma que suas credenciais estão funcionando.
Conecte o MCP e autentique-se:
claude mcp add --transport http Profound http://107.21.107.99:8081/mcp
O servidor autentica via OAuth (WorkOS). No Claude Code, execute /mcp, escolha Profound e conclua o login no navegador — o Claude Code também solicita automaticamente na primeira vez que uma ferramenta Profound é chamada. Quando /mcp mostrar Profound como connected, peça ao Claude:
Gere cinquenta aeroportos reais — códigos IATA corretos, nomes, cidades, países e coordenadas. Salve-os como JSON em uma pasta
data, valide contra o nosso componente airport e então crie cada um como documento publicado via Profound MCP, em paralelo.
Abra airport → Variants para confirmar cerca de 50 aeroportos publicados. O app lê com a chave de API; o MCP grava com sua própria sessão WorkOS.
Cerca de 50 aeroportos, populados como variantes publicadas.
O scaffold é entregue sem estilos. Coloque um DESIGN.md (um bloco @theme do Tailwind v4 mais tokens) na raiz do projeto — um seu ou faça o download em refero.design. Em seguida, peça ao Claude:
Leia o DESIGN.md. Configure o Tailwind v4 e conecte o tema e as fontes. Use
next/fontpara as fontes, não uma importação do Google em tempo de execução. Apenas estilos — nada de páginas ou componentes ainda.
Confirme que src/app/globals.css contém @import "tailwindcss"; e o bloco @theme, e que localhost:3000 exibe os tokens.
Construa a camada de renderização: os elementos de interface, os componentes React, a rota, os bindings CEL e a tradução.
No admin, Create new component quatro vezes (sem Route Slug). Para cada um, adicione os campos como Text, a menos que indicado, defina o status como Active e adicione a tag UI Element em Settings → Tags:
nav → brandheadline → title, subtitlebody → code, city, country, latitude (Number), longitude (Number)footer → textbody.latitude e body.longitude precisam ser Number para combinar com o componente airport.
Cada elemento de interface é o seu próprio componente — aqui o body, definido como Active com a tag UI Element.
Os quatro elementos de interface ao lado do componente airport.
bun run generate-schemas
Peça ao Claude:
Construa quatro componentes React — nav, headline, body, footer — em
components/. Cada um recebe uma única propcontenttipada comoBlockComponentProps<T>decms-renderer/lib/types, ondeTé o tipo gerado do elemento, e lê seus campos a partir decontent. Registre todos os quatro no registro da rota coringa pelo nome do componente. Estilize-os com o nosso sistema de design, mas como componentes próprios — não copie o layout do site de origem. Nav: marca à esquerda. Headline: nome do aeroporto com um subtítulocode · city, country. Body: painel de detalhes com código, cidade, país e coordenadas. Footer: uma linha estática. Somente layout e estilo.
O Claude cria os quatro componentes e preenche o registro em src/app/[...slug]/page.tsx:
const registry = { nav: Nav, headline: Headline, body: Body, footer: Footer };
Duas regras: cada componente lê seus campos a partir de content (não como props separadas), e as chaves do registro precisam corresponder exatamente aos nomes dos componentes no CMS — um nome diferente renderiza em branco.
No admin, vá para Pages → Create page e defina o padrão /{airport_code}. Em Dynamic Segment Mappings, mapeie airport_code → o componente airport, campo slug code. Salve — você será levado ao Page Builder. Verifique se /JFK resolve.
Adicionando um elemento de interface à página a partir da aba Custom.
Os quatro elementos de interface adicionados à ligação de JFK no Page Builder.
Escolha a ligação JFK → Add UI Element → aba Custom → adicione nav, headline, body, footer nessa ordem. A Profound propaga o conjunto para cada ligação de aeroporto.
Preencha cada campo. Valores estáticos (marca da nav, texto do rodapé): digite diretamente. Valores dinâmicos: alterne para dinâmico e escreva CEL. A consulta compartilhada é documents.get("airport", meta.params.airport_code).
| Campo | Valor 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 (e .longitude) |
nav.brand, footer.text | strings estáticas |
Clique em Publish na página (canto superior direito).
Abra localhost:3000/JFK, depois /SFO, /LAX — o mesmo template, aeroportos diferentes.
A página finalizada renderizando os dados de JFK, em inglês.
Traduza os componentes primeiro. No admin, abra cada componente (qualquer componente — não precisa ser um elemento de interface) e clique em Translate → Submit. A Profound traduz o conteúdo para todos os 35 idiomas de uma vez, incluindo os valores estáticos dos campos. Faça isso antes de editar a rota ou mexer em qualquer CEL.
Translate → Submit envia um componente para todos os 35 idiomas de uma só vez.
Adicione a dimensão de idioma. Em Pages, altere o padrão para /{language}/{airport_code}. Adicione um Dynamic Segment Mapping para language → o componente de sistema language, campo slug code. Salve e verifique se /en/JFK resolve.
Adicionando o segmento {language} à rota.
Aponte cada campo traduzível para a busca traduzida. Internacionalizar a página significa trocar todo campo dependente de idioma — não apenas a manchete — de documents.get(...) para documents.translated("airport", meta.params.airport_code, meta.params.language):
| Campo | CEL traduzido |
|---|---|
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 (e .country) |
Deixe o código IATA code e as coordenadas com documents.get — eles são idênticos em todos os idiomas. nav.brand e footer.text já foram cobertos pela tradução do componente no passo 1.
Quando tudo estiver concluído, /fr/SFO, /de/SFO etc. serão renderizados totalmente traduzidos.
Envie para o GitHub:
git init
git add -A
git commit -m "Diretório de aeroportos"
gh repo create airports --public --source=. --push
Importe na Vercel: Add New → Project → importe o repositório airports. Adicione as variáveis de ambiente — PROFOUND_API_KEY, NEXT_PUBLIC_PROFOUND_WEBSITE_ID, NEXT_PUBLIC_CMS_API_URL e, opcionalmente, NEXT_PUBLIC_BUNNY_CDN_URL — depois clique em Deploy. Visite /en/JFK e /fr/SFO. Cada futuro git push gera um novo deploy.
Ambos já vêm no scaffold.
<Refresher> em layout.tsx atualiza a página que você está visualizando quando edita e salva no admin — sem novo deploy.?edit_mode=true a qualquer URL (por exemplo, …/en/JFK?edit_mode=true) para ver as sobreposições de edição. Visitantes públicos continuam vendo a página limpa.?edit_mode=true mostra a interface do editor sobre a página ao vivo.
Cinquenta aeroportos, 35 idiomas, em produção — descritos uma vez e preenchidos por dados: uma rota, quatro componentes React e alguns bindings CEL. O CMS guarda o conteúdo, seu código o renderiza e o CEL conecta tudo.