custom-pages-and-apis

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

EventCatalog Custom Pages & APIs

EventCatalog 自定义页面与 API

Build user-defined pages and API routes that are served by EventCatalog itself — with full access to catalog data (domains, services, events, teams, ...) through a stable, documented toolkit.
Custom pages live in a
pages/
folder at the root of the catalog and are served under a configurable URL prefix (default
/custom
). API routes live in
pages/api/
and require SSR mode.
构建由 EventCatalog 自身提供的用户自定义页面和 API 路由,并通过稳定、已文档化的工具包完整访问 catalog 数据(domain、service、event、team 等)。
自定义页面位于 catalog 根目录的
pages/
文件夹中,并通过可配置的 URL 前缀提供访问(默认
/custom
)。API 路由位于
pages/api/
中,并要求启用 SSR 模式。

Requirements (check these FIRST)

前置条件(首先检查这些)

Before writing any files, verify all three. Generating pages that silently 404 is the most common failure mode of this feature.
  1. Scale plan — custom pages are an EventCatalog Scale feature. The license key must be configured (usually the
    EVENTCATALOG_SCALE_LICENSE_KEY
    env var /
    .env
    file). Without a Scale license the routes are simply not served (404) — the dev server prints a warning (
    Custom pages require the Scale plan
    ) but pages fail silently otherwise. If the user doesn't have a Scale key, tell them up front instead of generating files — and let them know they can get a free 30-day trial key from eventcatalog.cloud.
  2. Core version — requires
    @eventcatalog/core
    4.1.0 or later. Check the catalog's
    package.json
    .
  3. SSR for API routes only —
    .astro
    pages work in any output mode, but anything under
    pages/api/
    requires
    output: "server"
    in
    eventcatalog.config.js
    . A production build fails with a hard error if API routes exist in static mode (dev only warns). See references/api-routes.md.
在写入任何文件之前,务必验证以下三项。生成页面后静默返回 404 是此功能最常见的故障模式。
  1. Scale 套餐 — 自定义页面是 EventCatalog Scale 功能。必须配置 license key(通常为
    EVENTCATALOG_SCALE_LICENSE_KEY
    环境变量或
    .env
    文件)。没有 Scale license 时,这些路由将不会被提供(404) — dev server 会打印警告(
    Custom pages require the Scale plan
    ),否则页面会静默失效。如果用户没有 Scale key,应提前告知用户,而不是直接生成文件;同时说明用户可以从 eventcatalog.cloud 获取免费 30 天试用 key。
  2. 核心版本 — 要求
    @eventcatalog/core
    为 4.1.0 或更高版本。检查 catalog 的
    package.json
    。
  3. 仅 API 路由要求 SSR —
    .astro
    页面在任何输出模式下均可工作,但
    pages/api/
    下的任何内容都要求在
    eventcatalog.config.js
    中设置
    output: "server"
    。如果 API 路由在 static 模式下存在,生产构建会因硬错误而失败(开发模式仅会警告)。参见 references/api-routes.md。

Instructions

指令

Step 1: Locate the catalog

第 1 步:定位 catalog

Find the user's EventCatalog project (look for
eventcatalog.config.js
). Then check:
  • Does
    pages/
    already exist? Read what's there — including
    pages/homepage.astro
    , which is a special file (it replaces the catalog homepage at
    /
    , not served under the prefix).
  • What is the configured prefix? Read
    pages.prefix
    from
    eventcatalog.config.js
    (default
    custom
    ). All generated links must use it.
  • What output mode is set (
    output: "static"
    or
    "server"
    )?
  • Does the catalog have a
    components/
    folder? Files in it are importable as
    @catalog/components/*
    .
找到用户的 EventCatalog 项目(查找
eventcatalog.config.js
)。然后检查:
  • pages/
    是否已经存在?读取其中的内容 — 包括
    pages/homepage.astro
    ,这是一个特殊文件(它会替换
    /
    处的 catalog 主页,而不会通过前缀提供访问)。
  • 配置的前缀是什么?从
    eventcatalog.config.js
    中读取
    pages.prefix
    (默认值为
    custom
    )。所有生成的链接都必须使用该前缀。
  • 当前使用什么输出模式(
    output: "static"
    或
    "server"
    )?
  • catalog 是否包含
    components/
    文件夹?其中的文件可通过
    @catalog/components/*
    导入。

Step 2: Understand what the user wants to build

第 2 步:了解用户想构建什么

Common asks and where they land:
User wantsFile to createURL
A content/dashboard page
pages/reports.astro
/custom/reports
A custom homepage
pages/homepage.astro
/
(replaces default homepage)
A section with an index
pages/tools/index.astro
/custom/tools
A dynamic page
pages/reports/[id].astro
/custom/reports/:id
A JSON API endpoint
pages/api/stats.ts
/custom/api/stats
A dynamic API endpoint
pages/api/teams/[id].ts
/custom/api/teams/:id
Shared partials/components
pages/_components/Card.astro
never routed (underscore prefix)
Full routing rules (extensions, index handling, underscore convention, reserved prefixes, prefix validation): references/routing.md.
常见需求及对应文件:
用户需求要创建的文件URL
内容/仪表盘页面
pages/reports.astro
/custom/reports
自定义主页
pages/homepage.astro
/
(替换默认主页)
带索引的区块
pages/tools/index.astro
/custom/tools
动态页面
pages/reports/[id].astro
/custom/reports/:id
JSON API endpoint
pages/api/stats.ts
/custom/api/stats
动态 API endpoint
pages/api/teams/[id].ts
/custom/api/teams/:id
共享 partial/component
pages/_components/Card.astro
不提供路由(下划线前缀)
完整路由规则(扩展名、index 处理、下划线约定、保留前缀、前缀验证):references/routing.md。

Step 3: Build pages with the toolkit

第 3 步:使用工具包构建页面

Always prefer the stable public toolkit over EventCatalog internals:
  • @catalog/layouts/Layout.astro
    — the EventCatalog page shell (header, nav, optional resource sidebar). Props:
    title
    (required),
    description?
    ,
    sidebar?
    (default
    true
    ),
    showHeader?
    (default
    true
    ).
  • @catalog/utils
    — cached collection getters:
    getDomains
    ,
    getServices
    ,
    getSystems
    ,
    getEvents
    ,
    getCommands
    ,
    getQueries
    ,
    getFlows
    ,
    getChannels
    ,
    getEntities
    ,
    getAgents
    ,
    getContainers
    ,
    getDataProducts
    ,
    getAdrs
    ,
    getTeams
    ,
    getUsers
    , plus
    getItemsFromCollectionByIdAndSemverOrLatest
    for semver resolution. Pass
    { getAllVersions: false }
    to get only latest versions.
  • @catalog/components/*
    — the user's own components from their catalog's
    components/
    folder.
Minimal page:
astro
---
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>
Key conventions when generating page code:
  • Tailwind works out of the box. For colors, use EventCatalog theme variables so pages respect light/dark mode:
    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))]
    . Never use
    dark:
    variants.
  • Collection entries are Astro content entries: data is on
    entry.data
    (e.g.
    entry.data.id
    ,
    entry.data.name
    ,
    entry.data.version
    ,
    entry.data.summary
    ). Entry ids follow
    {id}-{version}
    .
  • Link to catalog docs pages as
    /docs/{collection}/{id}/{version}
    (e.g.
    /docs/services/OrderService/1.0.0
    ).
  • Put shared partials in
    pages/_components/
    and import them with relative paths.
  • Do NOT import from EventCatalog internals (
    @components/*
    ,
    @utils/*
    ,
    @layouts/*
    ). They resolve, but they are not a stable contract and can break on any release. Only
    @catalog/*
    is public API.
Full toolkit reference (all getter options, Layout props, entry shape): references/toolkit.md. Complete working examples (external data fetch, dynamic routes, nav partials, API endpoints): references/examples.md.
始终优先使用稳定的公开工具包,而不是 EventCatalog 内部实现:
  • @catalog/layouts/Layout.astro
    — EventCatalog 页面外壳(页头、导航、可选的 resource sidebar)。Props:
    title
    (必填)、
    description?
    、
    sidebar?
    (默认值为
    true
    )、
    showHeader?
    (默认值为
    true
    )。
  • @catalog/utils
    — 带缓存的 collection getter:
    getDomains
    、
    getServices
    、
    getSystems
    、
    getEvents
    、
    getCommands
    、
    getQueries
    、
    getFlows
    、
    getChannels
    、
    getEntities
    、
    getAgents
    、
    getContainers
    、
    getDataProducts
    、
    getAdrs
    、
    getTeams
    、
    getUsers
    ,以及用于 semver 解析的
    getItemsFromCollectionByIdAndSemverOrLatest
    。传入
    { getAllVersions: false }
    可只获取最新版本。
  • @catalog/components/*
    — 用户 catalog 自身
    components/
    文件夹中的组件。
最简页面:
astro
---
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 主题变量,使页面适应 light/dark mode:
    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:
    variants。
  • Collection entry 是 Astro content entry:数据位于
    entry.data
    (例如
    entry.data.id
    、
    entry.data.name
    、
    entry.data.version
    、
    entry.data.summary
    )。Entry ID 遵循
    {id}-{version}
    格式。
  • 将 catalog 文档页链接为
    /docs/{collection}/{id}/{version}
    (例如
    /docs/services/OrderService/1.0.0
    )。
  • 将共享 partial 放在
    pages/_components/
    中,并通过相对路径导入。
  • 不要从 EventCatalog 内部模块(
    @components/*
    、
    @utils/*
    、
    @layouts/*
    )导入。它们虽然可以解析,但并非稳定 contract,可能在任何版本更新中失效。只有
    @catalog/*
    是公开 API。
完整工具包参考(所有 getter 选项、Layout props、entry 结构):references/toolkit.md。 完整可运行示例(外部数据获取、动态路由、nav partial、API endpoint):references/examples.md。

Step 4: Wire pages into the navigation

第 4 步:将页面接入导航

Pages are reachable by URL immediately, but users usually want them in the vertical navigation. Add a group to
navigation.groups
in
eventcatalog.config.js
— remembering that providing
groups
replaces the entire default nav
, so include the built-ins the user still wants:
js
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' }] },
  ],
}
  • Built-in item ids:
    home
    ,
    docs
    ,
    catalog
    ,
    schemas
    ,
    schema-insights
    ,
    teams
    ,
    users
    ,
    settings
    ,
    studio
    .
  • Custom items need
    href
    ;
    icon
    is any lucide-react icon name (e.g.
    Workflow
    ,
    Github
    ,
    ChartBar
    ).
  • Use
    match
    (string or array) to keep an item highlighted on child routes, e.g.
    match: ['/custom/reports', '/custom/reports/**']
    .
  • If the config has no
    navigation.groups
    yet and the user only wants one link added, ask before replacing the default nav — or skip nav wiring and just share the URL.
页面可以通过 URL 立即访问,但用户通常希望将其显示在垂直导航中。在
eventcatalog.config.js
的
navigation.groups
中添加一个 group — 请注意,提供
groups
会替换整个默认导航
,因此应包含用户仍想保留的内置项:
js
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' }] },
  ],
}
  • 内置 item ID:
    home
    、
    docs
    、
    catalog
    、
    schemas
    、
    schema-insights
    、
    teams
    、
    users
    、
    settings
    、
    studio
    。
  • 自定义 item 必须提供
    href
    ;
    icon
    可以是任意 lucide-react icon 名称(例如
    Workflow
    、
    Github
    、
    ChartBar
    )。
  • 使用
    match
    (字符串或数组)让 item 在子路由上保持选中状态,例如
    match: ['/custom/reports', '/custom/reports/**']
    。
  • 如果 config 中尚无
    navigation.groups
    ,且用户只想添加一个 link,应先询问是否要替换默认 nav — 或者跳过 nav 接入,只分享 URL。

Step 5: Editor support (recommended)

第 5 步:编辑器支持(推荐)

VS Code resolves imports from the nearest
tsconfig.json
, so without one the
@catalog/*
imports show "cannot find module" warnings (the build still works — aliases are resolved by EventCatalog at runtime). Create a
tsconfig.json
at the catalog root pointing at the generated
.eventcatalog-core
directory:
jsonc
{
  // 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/*"],
      "@catalog/layouts/*": [".eventcatalog-core/src/toolkit/layouts/*"],
      "@catalog/utils": [".eventcatalog-core/src/toolkit/utils/index.ts"],
      "@catalog/utils/*": [".eventcatalog-core/src/toolkit/utils/*"]
    }
  },
  "include": ["pages/**/*", "components/**/*"]
}
Note:
.eventcatalog-core
is generated the first time the dev server runs (
npm run dev
), so the paths resolve after the first run. Tell the user to reload the TS/Astro language server after adding this file.
VS Code 会从最近的
tsconfig.json
解析 import,因此如果没有该文件,
@catalog/*
import 会显示“cannot find module”警告(构建仍可正常工作 — alias 由 EventCatalog 在运行时解析)。在 catalog 根目录创建一个指向生成的
.eventcatalog-core
目录的
tsconfig.json
:
jsonc
{
  // 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/*"],
      "@catalog/layouts/*": [".eventcatalog-core/src/toolkit/layouts/*"],
      "@catalog/utils": [".eventcatalog-core/src/toolkit/utils/index.ts"],
      "@catalog/utils/*": [".eventcatalog-core/src/toolkit/utils/*"]
    }
  },
  "include": ["pages/**/*", "components/**/*"]
}
注意:
.eventcatalog-core
会在首次运行 dev server(
npm run dev
)时生成,因此这些路径会在首次运行后解析。添加此文件后,告知用户重新加载 TS/Astro language server。

Step 6: Verify

第 6 步:验证

  1. Start the dev server (
    npm run dev
    ) — or if it's already running, no restart is needed: EventCatalog watches the
    pages/
    folder and picks up new/removed files automatically (adding/removing a file triggers a brief automatic server restart; edits hot-reload).
  2. Open the page at its prefixed URL (e.g.
    http://localhost:3000/custom/reports
    ) and confirm it renders inside the EventCatalog shell.
  3. For API routes, curl the endpoint and check the JSON response.
  4. If a page 404s, check in order: Scale license configured? Correct prefix in the URL? File has a routable extension (
    .astro
    ,
    .ts
    ,
    .js
    ,
    .mjs
    )? Not under an underscore-prefixed folder?
  1. 启动 dev server(
    npm run dev
    )— 如果它已经在运行,则无需重启:EventCatalog 会监控
    pages/
    文件夹,并自动识别新增或删除的文件(新增或删除文件会触发短暂的自动 server 重启;编辑则会热重载)。
  2. 使用带前缀的 URL 打开页面(例如
    http://localhost:3000/custom/reports
    ),并确认页面能在 EventCatalog shell 中正常呈现。
  3. 对于 API 路由,使用 curl 请求 endpoint,并检查 JSON 响应。
  4. 如果页面返回 404,请按以下顺序检查:是否配置了 Scale license?URL 中的前缀是否正确?文件是否使用可路由的扩展名(
    .astro
    、
    .ts
    、
    .js
    、
    .mjs
    )?路径是否包含以下划线开头的文件夹?

Troubleshooting

故障排除

SymptomCause
All custom pages 404, warning
Custom pages require the Scale plan
No/invalid Scale license — routes are not injected without it. A free 30-day trial key is available at eventcatalog.cloud
Build fails: API routes require
output: "server"
pages/api/**
exists but config is static — set
output: "server"
or remove the API routes
Page 404s but others workUnderscore-prefixed path segment, non-routable extension, or wrong prefix
Cannot find module '@catalog/utils'
in editor only
Missing catalog-level
tsconfig.json
(Step 5); build is unaffected
Config error:
pages.prefix ... is reserved
Prefix collides with a core route — see reserved list in references/routing.md
Homepage unchanged after adding
pages/homepage.astro
Requires Scale license; also note homepage is served at
/
, not under the prefix
症状原因
所有自定义页面均返回 404,并出现警告
Custom pages require the Scale plan
Scale license 缺失或无效 — 没有 license 时不会注入路由。可在 eventcatalog.cloud 获取免费 30 天试用 key
构建失败:API routes require
output: "server"
pages/api/**
存在,但 config 使用 static 模式 — 设置
output: "server"
或移除 API 路由
某个页面返回 404,但其他页面正常路径段以下划线开头、扩展名不可路由,或前缀错误
仅在编辑器中出现
Cannot find module '@catalog/utils'
缺少 catalog 级别的
tsconfig.json
(第 5 步);构建不受影响
配置错误:
pages.prefix ... is reserved
前缀与核心路由冲突 — 参见 references/routing.md 中的保留列表
添加
pages/homepage.astro
后主页仍未变化
需要 Scale license;另请注意,主页通过
/
提供访问,而不是通过前缀访问

Reference Files

参考文件

  • references/routing.md — file-to-URL mapping, prefix config and validation, reserved prefixes, underscore convention, homepage.astro
  • references/toolkit.md —
    @catalog/layouts
    ,
    @catalog/utils
    ,
    @catalog/components
    in full detail
  • references/api-routes.md — API endpoints, SSR requirement, response patterns
  • references/examples.md — complete working examples to adapt
  • references/routing.md — 文件到 URL 的映射、prefix 配置与验证、保留前缀、下划线约定、homepage.astro
  • references/toolkit.md —
    @catalog/layouts
    、
    @catalog/utils
    、
    @catalog/components
    的完整详情
  • references/api-routes.md — API endpoint、SSR 要求、响应模式
  • references/examples.md — 可直接改编的完整可运行示例