关于 custom-pages-and-apis
为 EventCatalog 编写自定义页面和 API 路由的技能,面向扩展目录界面的开发者。它指导使用稳定的公开工具包读取目录数据,并处理路由、导航与运行模式要求。
主要功能
- 01生成内容页、首页和动态页面
- 02添加需 SSR 的 API 路由
- 03通过公开工具包读取目录数据
- 04配置自定义路由与导航
- 05检查版本和构建模式要求
适用场景
- 01为目录添加报告或仪表板
- 02创建展示目录数据的自定义首页
- 03为目录提供 JSON API 端点
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ event-catalog/ skills --skill custom-pages-and-apis安装后在 Claude Code 中输入/custom-pages-and-apis确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-routes.mdexamples.mdrouting.mdtoolkit.md详细介绍
EventCatalog 自定义页面和 API
构建由 EventCatalog 自身提供服务的用户自定义页面和 API 路由,并通过稳定且有文档说明的工具包,完整访问目录数据(域、服务、事件、团队等)。
自定义页面位于目录根目录下的 pages/ 文件夹中,并通过可配置的 URL 前缀提供服务(默认为 /custom)。API 路由位于 pages/api/ 中,且需要 SSR 模式。
要求(请先检查)
编写任何文件之前,请确认以下两项。
- Core 版本 — 从
@eventcatalog/core5.0.0 开始,所有目录均可使用自定义页面(无需套餐或许可证密钥)。4.1.0–4.x 版本仅在拥有 Scale 许可证密钥时才提供自定义页面,而 Layout 的fullWidth属性需要 4.12 或更高版本。检查目录的package.json;如果使用的是 4.x,请建议升级。 - 仅 API 路由需要 SSR —
.astro页面适用于任何输出模式,但pages/api/下的任何内容都要求在eventcatalog.config.js中设置output: "server"。如果静态模式下存在 API 路由,生产构建会报错中止(开发模式下只会发出警告)。请参阅 references/api-routes.md。
说明
第 1 步:定位目录
找到用户的 EventCatalog 项目(查找 eventcatalog.config.js)。然后检查:
- 是否已存在
pages/?阅读其中的内容,包括pages/homepage.astro;这是一个特殊文件(它会替换目录在/下的主页,而不是通过前缀提供服务)。如果没有此文件,目录会显示内置的仪表板主页。 - 配置了什么前缀?从
eventcatalog.config.js中读取pages.prefix(默认为custom)。所有生成的链接都必须使用该前缀。 - 设置了什么输出模式(
output: "static"或"server")? - 目录中是否有
components/文件夹?其中的文件可通过@catalog/components/*导入。 eventcatalog.config.js中是否设置了landingPage?如果设置了,/会重定向到该页面,且不会显示自定义主页。
第 2 步:了解用户想构建什么
常见需求及对应位置:
| 用户需求 | 要创建的文件 | URL |
|---|---|---|
| 内容页/仪表板页面 | pages/reports.astro | /custom/reports |
| 自定义主页 | pages/homepage.astro | /(替换默认主页) |
| 带索引页的区块 | pages/tools/index.astro | /custom/tools |
| 动态页面 | pages/reports/[id].astro | /custom/reports/:id |
| JSON API 端点 | pages/api/stats.ts | /custom/api/stats |
| 动态 API 端点 | pages/api/teams/[id].ts | /custom/api/teams/:id |
| 共享局部内容/组件 | pages/_components/Card.astro | 永不参与路由(下划线前缀) |
完整路由规则(扩展名、索引处理、下划线约定、保留前缀、前缀验证):references/routing.md。
自定义主页: pages/homepage.astro 已在 EventCatalog 外壳内渲染,因此不要用 Layout 包裹它。它会在 Astro.props.components 上接收 EventCatalog 的组件,包括 CatalogDashboard(默认仪表板,可选 title 和 description),因此主页可以扩展仪表板,而不必重新构建:
---
const { CatalogDashboard } = Astro.props.components;
---
<div class="not-prose">
<CatalogDashboard title="Acme Catalog" description="Our domains, systems, services and messages." />
</div>
第 3 步:使用工具包构建页面
始终优先使用稳定的公共工具包,而不是 EventCatalog 内部实现:
@catalog/layouts/Layout.astro— EventCatalog 页面外壳(页眉、导航栏、可选的资源侧边栏)。属性:title(必填)、description?、sidebar?(默认值为true)、showHeader?(默认值为true)、fullWidth?(默认值为false;页面会延伸至边缘,不使用 EventCatalog 的页面内边距,适用于自行控制布局的页面)。@catalog/utils— 带缓存的集合获取器:getDomains、getServices、getSystems、getEvents、getCommands、getQueries、getFlows、getChannels、getEntities、getAgents、getContainers、getDataProducts、getAdrs、getTeams、getUsers,以及用于 semver 解析的getItemsFromCollectionByIdAndSemverOrLatest。传入{ getAllVersions: false }可只获取最新版本。@catalog/components/*— 用户自己目录的components/文件夹中的组件。
最简页面:
---
import Layout from '@catalog/layouts/Layout.astro';
import { getServices } from '@catalog/utils';
const services = await getServices({ getAllVersions: false });
---
<Layout title="Service Report" description="All services in our architecture" sidebar={false}>
<div class="max-w-4xl mx-auto p-8">
<h1 class="text-2xl font-bold text-[rgb(var(--ec-page-text))]">Services ({services.length})</h1>
<ul>
{services.map((service) => (
<li>
<a href={`/docs/services/${service.data.id}/${service.data.version}`}>{service.data.name}</a>
</li>
))}
</ul>
</div>
</Layout>
生成页面代码时的关键约定:
- Tailwind 开箱即用。 使用 EventCatalog 主题变量设置颜色,让页面支持浅色/深色模式:
text-[rgb(var(--ec-page-text))]、bg-[rgb(var(--ec-page-bg))]、border-[rgb(var(--ec-page-border))]、bg-[rgb(var(--ec-card-bg))]、text-[rgb(var(--ec-accent))]。切勿使用dark:变体。 - 集合条目是 Astro 内容条目:数据位于
entry.data中(例如entry.data.id、entry.data.name、entry.data.version、entry.data.summary)。条目 ID 格式为{id}-{version}。 - 目录文档页面的链接格式为
/docs/{collection}/{id}/{version}(例如/docs/services/OrderService/1.0.0)。团队和用户没有版本:/docs/teams/{id}、/docs/users/{id}。资源列表位于/discover/{type}(例如/discover/services、/discover/events)。 owners和团队的members是引用({ id, collection }),不是完整条目。通过 ID 在getTeams()/getUsers()中查找,以显示名称。- 将共享的局部组件放在
pages/_components/中,并使用相对路径导入。 - 请勿从 EventCatalog 内部模块(
@components/*、@utils/*、@layouts/*)导入。虽然这些模块可以解析,但它们不是稳定的接口,任何版本发布都可能导致其失效。只有@catalog/*是公共 API。
完整工具包参考(所有获取器选项、Layout 属性、条目结构):references/toolkit.md。 完整可运行示例(外部数据获取、动态路由、导航栏局部组件、API 端点):references/examples.md。
第 4 步:将页面接入导航栏
页面可立即通过 URL 访问,但用户通常希望页面显示在垂直导航栏中。在 eventcatalog.config.js 的 navigation.groups 中添加一个分组——请记住,提供 groups 会替换整个默认导航栏,因此要保留用户仍需要的内置项:
navigation: {
groups: [
{ id: 'main', items: [{ id: 'home' }, { id: 'docs' }] },
{ id: 'browse', label: 'Browse', items: [{ id: 'catalog' }, { id: 'schemas' }] },
{
id: 'my-pages',
label: 'My Company',
items: [
{ id: 'reports', label: 'Reports', href: '/custom/reports', icon: 'ChartBar' },
{ id: 'team', label: 'Our Team', href: '/custom/team', icon: 'UsersRound' },
],
},
{ id: 'settings-group', position: 'bottom', items: [{ id: 'settings' }] },
],
}
- 内置项 ID:
home、docs、catalog、schemas、schema-insights、teams、users、settings、studio。 - 自定义项需要
href;icon可以是任意 lucide-react 图标名称(例如Workflow、Github、ChartBar)。 - 使用
match(字符串或数组)让子路由上的项保持高亮,例如match: '/custom/reports'。匹配采用普通前缀检查(不支持 glob),因此/custom/reports/2024也会匹配。 - 如果配置中尚无
navigation.groups,而用户只想添加一个链接,请在替换默认导航栏前先征求同意——或者跳过导航栏接入,只分享 URL。
步骤 5:编辑器支持(推荐)
VS Code 会从最近的 tsconfig.json 解析导入,因此如果没有该文件,@catalog/* 导入会显示“找不到模块”警告(构建仍然有效——别名由 EventCatalog 在运行时解析)。在目录根目录创建 tsconfig.json,指向已安装的 @eventcatalog/core 包中的工具包:
{
// Editor support (IntelliSense, go-to-definition) for custom pages.
// These aliases mirror the ones the EventCatalog build provides at runtime.
"compilerOptions": {
"baseUrl": ".",
"allowJs": true,
"jsx": "preserve",
"paths": {
"@catalog/components/*": ["components/*", "federated/components/*"],
"@catalog/layouts/*": ["node_modules/@eventcatalog/core/eventcatalog/src/toolkit/layouts/*"],
"@catalog/utils": ["node_modules/@eventcatalog/core/eventcatalog/src/toolkit/utils/index.ts"],
"@catalog/utils/*": ["node_modules/@eventcatalog/core/eventcatalog/src/toolkit/utils/*"]
}
},
"include": ["pages/**/*", "components/**/*"]
}
注意:较早的指南将这些路径指向 .eventcatalog-core/,但 EventCatalog 不再生成该目录(4.12+)。如果目录中有使用这些路径的旧 tsconfig.json,请更新它。添加此文件后,请告知用户重新加载 TS/Astro 语言服务器。
步骤 6:验证
- 启动开发服务器(
npm run dev)——或者,如果服务器已经在运行,则无需重启:EventCatalog 会监视pages/文件夹,并自动发现新增或移除的文件(添加或移除文件会触发短暂的自动服务器重启;编辑则会热重载)。 - 打开带前缀的页面 URL(例如
http://localhost:3000/custom/reports),确认页面在 EventCatalog 外壳中正常渲染。 - 对于 API 路由,使用 curl 请求端点并检查 JSON 响应。
- 如果页面返回 404,请依次检查:URL 中的前缀是否正确?文件是否具有可路由的扩展名(
.astro、.ts、.js、.mjs)?是否位于以下划线开头的文件夹中?
故障排除
| 症状 | 原因 |
|---|---|
所有自定义页面都返回 404,警告为 Custom pages require the Scale plan | 目录使用的是没有 Scale 密钥的 @eventcatalog/core 4.x——请升级到 5.x,届时所有目录都可以使用自定义页面 |
构建失败:API 路由要求 output: "server" | 存在 pages/api/**,但配置为静态模式——请设置 output: "server" 或移除 API 路由 |
| 页面返回 404,但其他页面正常 | 路径段以下划线开头、扩展名不可路由,或前缀错误 |
仅在编辑器中出现 Cannot find module '@catalog/utils' | 缺少目录级 tsconfig.json(步骤 5);不影响构建 |
配置错误:pages.prefix ... is reserved | 前缀与核心路由冲突——请参阅 references/routing.md 中的保留列表 |
添加 pages/homepage.astro 后主页没有变化 | eventcatalog.config.js 中设置了 landingPage(它会先重定向 /),或者你查看的是前缀下的页面——主页位于 / |
| 主页显示两个页眉/嵌套导航 | homepage.astro 被 Layout 包裹——请移除它;主页已在外壳中渲染 |
.json 文件导致意外路由或路由错误(例如,pages/data.json → /custom/data) | pages/ 中的 .json 文件会被识别为路由——请将数据文件放在以下划线开头的文件夹中(pages/_data/) |
参考文件
- references/routing.md — 文件到 URL 的映射、前缀配置与验证、保留前缀、下划线约定、homepage.astro
- references/toolkit.md —
@catalog/layouts、@catalog/utils、@catalog/components的详细说明 - references/api-routes.md — API 端点、SSR 要求、响应模式
- references/examples.md — 可供改编的完整可运行示例