一步步实操:在 Profound CMS 上构建国际化机场目录——使用一个参数化路由,为每个机场渲染页面,覆盖 35 种语言。
在 Profound CMS 上构建一个真正的、国际化的机场目录:使用一个 URL 模式为每个机场渲染页面,支持 35 种语言。你负责编写 Next.js 代码并手动搭建 CMS 结构;Claude Code(通过 Profound MCP)负责三件事——生成机场数据、接入设计系统以及生成四个 React 组件。整体分为三部分:设置、构建、上线。
/{language}/{airport_code}。cms-renderer 渲染。curl -fsSL https://bun.sh/install | bashgh)与已关联 GitHub 的 Vercel 账号。language)内置提供。cms-renderer SDK 和读取级 API Key 完成渲染。最终状态:CMS 中约 50 个机场、应用已接通读取权限、设计系统就绪。
在 Profound(WorkOS 认证)注册账号,创建名为 airports 的网站。复制两项信息:网站 ID(后台 URL 中的 UUID)以及 读取级 API Key(在 Deployments → Create API key 中生成)。应用只读,因此读取密钥即可。
bunx create-profound-next airports
cd airports
将凭据写入 .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
运行 bun dev 并打开 localhost:3000,确认连接成功。
airport 组件在后台进入 Components → Create new component,命名为 airport。添加六个字段:code、name、city、country(类型为 Text),latitude、longitude(类型为 Number)。将 code 标记为 Route Slug 字段,将状态设为 Active。所有字段保持可选;不添加任何 UI Element 标签。
airport 组件——六个字段,其中 code 设为 Route Slug。
bun run generate-schemas
这会在 generated/cms-schemas.ts 中生成 airportSchema(Zod)和 Airport(TypeScript 类型),同时验证凭据可用。
连接 MCP 并完成认证:
claude mcp add --transport http Profound http://107.21.107.99:8081/mcp
服务器通过 OAuth(WorkOS)认证。在 Claude Code 中运行 /mcp,选择 Profound,在浏览器完成登录 —— 首次调用 Profound 工具时,Claude Code 也会自动提示。待 /mcp 显示 Profound 为 connected 后,向 Claude 提示:
生成五十个真实机场——包含正确的 IATA 代码、名称、城市、国家和坐标。将它们作为 JSON 保存到
data文件夹,依据我们的 airport 组件进行验证,然后通过 Profound MCP 并行创建为已发布文档。
打开 airport → Variants,确认约 50 个已发布机场。应用使用 API Key 读取;MCP 通过其 WorkOS 会话写入。
约 50 个机场,作为已发布变体导入。
脚手架默认无样式。在项目根目录放置 DESIGN.md(包含 Tailwind v4 的 @theme 区块与令牌)——可自定义,或从 refero.design 下载。然后提示 Claude:
阅读 DESIGN.md,设置 Tailwind v4 并接入主题与字体。字体使用
next/font,不要在运行时通过 Google 引入。仅处理样式,不创建页面或组件。
确认 src/app/globals.css 已包含 @import "tailwindcss"; 以及 @theme 区块,并在 localhost:3000 上看到令牌。
构建渲染层:UI 元素、React 组件、路由、CEL 绑定与翻译。
在后台四次选择 Create new component(均无 Route Slug)。除标注外,字段类型为 Text,状态设为 Active,并在 Settings → Tags 中添加 UI Element 标签:
nav → brandheadline → title、subtitlebody → code、city、country、latitude(Number)、longitude(Number)footer → textbody.latitude 与 body.longitude 必须为 Number,以匹配 airport 组件。
每个 UI 元素都有独立组件——如图所示的 body,设为 Active 并带有 UI Element 标签。
四个 UI 元素与 airport 组件同列展示。
bun run generate-schemas
提示 Claude:
在
components/中构建四个 React 组件 —— nav、headline、body、footer。每个组件仅接收一个content属性,类型为cms-renderer/lib/types中的BlockComponentProps<T>,其中T为对应元素的生成类型,并通过content读取字段。在捕获全部路由的注册表中按组件名注册四个组件。使用我们的设计系统进行样式设计,但保持自有组件风格——不要照搬源站布局。Nav:品牌位于左侧。Headline:机场名称,副标题为code · city, country。Body:详情面板,显示代码、城市、国家与坐标。Footer:一行固定文案。仅处理布局与样式。
Claude 会在 components/ 中创建四个组件,并在 src/app/[...slug]/page.tsx 的注册表中填入:
const registry = { nav: Nav, headline: Headline, body: Body, footer: Footer };
两条规则:每个组件必须从 content 读取字段(不可单独传参);注册表键名需与 CMS 组件名完全一致——否则渲染为空。
在后台进入 Pages → Create page,设置模式 /{airport_code}。在 Dynamic Segment Mappings 中,将 airport_code 映射到 airport 组件,Slug 字段选择 code。保存后进入 Page Builder。验证 /JFK 可访问。
从 Custom 标签页向页面添加 UI 元素。
在 JFK 绑定中加入的四个 UI 元素。
选择 JFK 绑定 → Add UI Element → Custom 标签页 → 依次添加 nav、headline、body、footer。Profound 会将该组合复制到每个机场绑定。
填写字段。静态值(导航品牌、页脚文案):直接输入。动态值:切换为动态模式并编写 CEL。通用查询为 documents.get("airport", meta.params.airport_code)。
| 字段 | 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(与 .longitude) |
nav.brand、footer.text | 静态字符串 |
点击右上角 Publish 发布页面。
依次打开 localhost:3000/JFK、/SFO、/LAX——同一模板,不同机场数据。
最终页面,以英文展示 JFK 的数据。
先翻译组件。 在后台打开任意组件(不一定是 UI 元素),点击 Translate → Submit。Profound 会一次性把内容翻译成 35 种语言,包含静态字段值。在修改路由或 CEL 前完成此操作。
Translate → Submit 一次推送至全部 35 种语言。
加入语言维度。 在 Pages 中将模式改为 /{language}/{airport_code}。新增一个 Dynamic Segment Mapping,将 language 映射到内置的 language 系统组件,Slug 字段选 code。保存并验证 /en/JFK 可访问。
为路由添加 {language} 段。
让所有可翻译字段指向译文查询。 实现页面国际化意味着将每个与语言相关的字段——不仅仅是标题——从 documents.get(...) 切换为 documents.translated("airport", meta.params.airport_code, meta.params.language):
| 字段 | 翻译后 CEL |
|---|---|
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(与 .country) |
IATA code 与坐标使用 documents.get 保持原值 —— 各语言一致。nav.brand 与 footer.text 已在步骤 1 的组件翻译中覆盖。
完成上述三步后,/fr/SFO、/de/SFO 等地址即可完整呈现对应语言内容。
推送到 GitHub:
git init
git add -A
git commit -m "Airport directory"
gh repo create airports --public --source=. --push
导入 Vercel:选择 Add New → Project,导入 airports 仓库。添加环境变量 —— PROFOUND_API_KEY、NEXT_PUBLIC_PROFOUND_WEBSITE_ID、NEXT_PUBLIC_CMS_API_URL,如需可选填 NEXT_PUBLIC_BUNNY_CDN_URL —— 然后点击 Deploy。访问 /en/JFK 与 /fr/SFO。此后每次 git push 都会触发重新部署。
脚手架自带这两项能力。
layout.tsx 中的 <Refresher> 会在后台保存编辑后刷新当前预览页面——无需重新部署。?edit_mode=true(例如 …/en/JFK?edit_mode=true)即可显示编辑覆盖层。公众访问仍看到正常页面。?edit_mode=true 会在上线页面叠加编辑器。
五十个机场、三十五种语言、实时上线——一次描述,数据驱动填充:一个路由、四个 React 组件,加上一些 CEL 绑定。CMS 承载内容,你的代码负责渲染,CEL 负责串联二者。