turbo-add

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Adding a New Theme to Turbo-Themes

向Turbo-Themes添加新主题

Turbo-themes uses a token-based theming system: theme definitions in
src/themes/packs/
define color tokens,
src/themes/registry.ts
collects them, the build generates CSS from tokens, the theme-selector package provides UI components, and the site plus example projects consume the themes.
Turbo-themes 采用基于Token的主题系统:
src/themes/packs/
中的主题定义用于定义颜色Token,
src/themes/registry.ts
收集这些Token,构建过程从Token生成CSS,theme-selector包提供UI组件,网站及示例项目则使用这些主题。

Related Skills

相关技能

  • stand-ts
    : TypeScript coding standards
  • commit
    : semantic commit format when committing changes
  • turbo-verify
    : use after implementation to verify completeness
  • stand-ts
    : TypeScript编码规范
  • commit
    : 提交更改时使用语义化提交格式
  • turbo-verify
    : 实现完成后用于验证完整性

How to Implement: Copy a Reference, Discover the Touchpoints

实现方法:参考现有主题,梳理所有关联点

Do NOT write theme packs from a template or trust a memorized file list. Instead:
  1. Pick a reference theme and mirror its files:
    • Synced theme with npm package:
      src/themes/packs/catppuccin.synced.ts
      +
      scripts/sync-catppuccin.mjs
    • Synced theme:
      src/themes/packs/rose-pine.synced.ts
    • Manual theme with license/source metadata:
      src/themes/packs/nord.ts
    • Manual theme:
      src/themes/packs/bulma.ts
      ,
      src/themes/packs/dracula.ts
  2. Discover every touchpoint by grepping for an existing theme's variant id (pick one from
    src/themes/registry.ts
    , e.g. a rose-pine or catppuccin variant):
    bash
    # Every file that mentions an existing variant — the new theme needs the
    # same touchpoints (packs, token JSON, icons, site data, examples, tests)
    rg -l 'rose-pine-moon' --hidden -g '!node_modules' -g '!dist'
    
    # Family-level touchpoints (type unions, family maps, vendor metadata)
    rg -l 'rose-pine' src/ packages/ apps/ scripts/
  3. Also check root-level registrations the greps can miss because they do not mention variant ids: the
    theme:sync
    script wiring in
    package.json
    and size limits in
    test/integration/bundle-size.test.ts
    .
  4. Verify with the current repo, not this skill: if a file in the grep output is generated (check for a "generated" header or a
    build
    /
    theme:sync
    script that writes it), update the source and rebuild instead of hand-editing.
请勿从模板编写主题包或依赖记忆的文件列表。请按以下步骤操作:
  1. 选择一个参考主题并复制其文件结构:
    • 与npm包同步的主题:
      src/themes/packs/catppuccin.synced.ts
      +
      scripts/sync-catppuccin.mjs
    • 同步主题:
      src/themes/packs/rose-pine.synced.ts
    • 带许可证/源元数据的手动主题:
      src/themes/packs/nord.ts
    • 手动主题:
      src/themes/packs/bulma.ts
      src/themes/packs/dracula.ts
  2. 通过搜索现有主题的变体ID梳理所有关联点(从
    src/themes/registry.ts
    中选择一个,例如rose-pine或catppuccin的变体):
    bash
    # 所有提及现有变体的文件——新主题需要相同的关联点(包、Token JSON、图标、站点数据、示例、测试)
    rg -l 'rose-pine-moon' --hidden -g '!node_modules' -g '!dist'
    
    # 主题系列级别的关联点(类型联合、系列映射、供应商元数据)
    rg -l 'rose-pine' src/ packages/ apps/ scripts/
  3. 同时检查根目录下的注册项,这些可能无法通过搜索找到,因为它们没有提及变体ID:
    package.json
    中的
    theme:sync
    脚本配置,以及
    test/integration/bundle-size.test.ts
    中的大小限制。
  4. 请以当前仓库为准,而非本技能文档:如果搜索结果中的文件是生成的(检查是否有“generated”标头或写入该文件的
    build
    /
    theme:sync
    脚本),请更新源文件并重新构建,而非手动编辑。

Files to Create

需要创建的文件

text
scripts/sync-<theme>.mjs                     # Optional: sync from npm package
src/themes/packs/<theme>.synced.ts           # Theme definitions (or <theme>.ts for manual)
schema/tokens/themes/<theme-id>.tokens.json  # W3C Design Token file, one per variant
assets/img/<theme-id>.png                    # Theme icon, one per variant
  • Theme pack: copy the structure of the reference pack —
    id
    ,
    name
    ,
    homepage
    ,
    license
    (spdx/url/copyright),
    source
    (package/version/repository for synced themes), and
    flavors
    with complete token groups (
    background
    ,
    text
    ,
    brand
    ,
    state
    ,
    border
    ,
    accent
    ,
    typography
    ,
    content
    ). Do NOT add
    iconUrl
    to flavors — icons resolve via
    VENDOR_ICON_MAP
    in theme-mapper.ts.
  • W3C token files: mirror an existing file in
    schema/tokens/themes/
    $value
    /
    $type
    format,
    $schema
    pointing to
    ../../turbo-themes.schema.json#/$defs/ThemeFile
    .
  • Icons: PNG per variant (typically 24x24), visually distinct for light/dark.
text
scripts/sync-<theme>.mjs                     # 可选:从npm包同步
src/themes/packs/<theme>.synced.ts           # 主题定义(手动主题则用<theme>.ts)
schema/tokens/themes/<theme-id>.tokens.json  # W3C设计Token文件,每个变体对应一个
assets/img/<theme-id>.png                    # 主题图标,每个变体对应一个
  • 主题包:复制参考包的结构——
    id
    name
    homepage
    license
    (spdx/url/copyright)、
    source
    (同步主题的包/版本/仓库),以及包含完整Token组(
    background
    text
    brand
    state
    border
    accent
    typography
    content
    )的
    flavors
    。请勿向
    flavors
    添加
    iconUrl
    ——图标通过theme-mapper.ts中的
    VENDOR_ICON_MAP
    解析。
  • W3C Token文件:复制
    schema/tokens/themes/
    中的现有文件格式——
    $value
    /
    $type
    格式,
    $schema
    指向
    ../../turbo-themes.schema.json#/$defs/ThemeFile
  • 图标:每个变体对应一张PNG图片(通常为24x24),亮色/暗色主题需视觉区分。

Sync Script Best Practices (if the theme has an npm palette package)

同步脚本最佳实践(若主题有npm调色板包)

Copy
scripts/sync-catppuccin.mjs
and adapt. Key rules:
  1. Output path must be
    src/themes/packs/
    — the registry imports from there, NOT
    packages/core/src/themes/packs/
    .
  2. Read the version from
    node_modules/<pkg>/package.json
    and populate
    source.version
    for traceability.
  3. Normalize hex colors — source packages include
    #
    inconsistently.
  4. Deterministic ordering — sort variant keys for reproducible builds.
  5. Add the script to
    theme:sync
    in package.json
    — the build pipeline must generate the file before TypeScript compilation.
复制
scripts/sync-catppuccin.mjs
并调整。关键规则:
  1. 输出路径必须为
    src/themes/packs/
    ——注册表从此处导入,而非
    packages/core/src/themes/packs/
  2. node_modules/<pkg>/package.json
    读取版本
    并填充
    source.version
    以保证可追溯性。
  3. 标准化十六进制颜色——源包中
    #
    的使用不一致。
  4. 确定排序——对变体键排序以保证构建可复现。
  5. 将脚本添加到package.json的
    theme:sync
    ——构建管道必须在TypeScript编译前生成该文件。

Files to Update

需要更新的文件

Enumerate with the discovery greps above; the recurring touchpoints are:
  • src/themes/registry.ts
    — import the pack and spread its flavors into
    allFlavors
  • packages/theme-selector/src/types.ts
    — add to the
    ThemeFamily
    type union
  • packages/theme-selector/src/constants.ts
    — add to
    THEME_FAMILIES
    (name + description)
  • packages/theme-selector/src/theme-mapper.ts
    — add to
    VENDOR_FAMILY_MAP
    ,
    VENDOR_ICON_MAP
    (string, or
    {light, dark}
    AppearanceIcons object when the family has both appearances), and
    FLAVOR_DESCRIPTIONS
    per variant
  • apps/site/src/data/theme-meta.ts
    single source of truth for the site: add to
    themeGroups
    ,
    themeNames
    (short dropdown labels), and
    themeIcons
    .
    validThemeIds
    is derived automatically;
    BaseLayout.astro
    and
    ThemeDropdown.astro
    are data-driven from this file — no direct edits there.
  • apps/site/src/pages/themes.astro
    — sidebar family section + JS
    themeNames
  • apps/site/src/pages/index.astro
    — hero preview strip buttons
  • scripts/prepare-style-dictionary.mjs
    — add to
    vendorMeta
    (name + homepage)
  • test/integration/bundle-size.test.ts
    — increase budget only if needed
  • package.json
    — append sync script to
    theme:sync
    (if using one)
通过上述搜索命令列出所有文件;常见的关联点包括:
  • src/themes/registry.ts
    ——导入主题包并将其
    flavors
    展开到
    allFlavors
  • packages/theme-selector/src/types.ts
    ——添加到
    ThemeFamily
    类型联合中
  • packages/theme-selector/src/constants.ts
    ——添加到
    THEME_FAMILIES
    (名称+描述)
  • packages/theme-selector/src/theme-mapper.ts
    ——添加到
    VENDOR_FAMILY_MAP
    VENDOR_ICON_MAP
    (字符串,或当主题系列包含两种外观时使用
    {light, dark}
    AppearanceIcons对象),以及每个变体对应的
    FLAVOR_DESCRIPTIONS
  • apps/site/src/data/theme-meta.ts
    ——站点的唯一数据源:添加到
    themeGroups
    themeNames
    (下拉菜单短标签)和
    themeIcons
    validThemeIds
    会自动推导;
    BaseLayout.astro
    ThemeDropdown.astro
    从此文件获取数据——请勿直接编辑这些文件。
  • apps/site/src/pages/themes.astro
    ——侧边栏主题系列章节+JS
    themeNames
  • apps/site/src/pages/index.astro
    ——首页预览条按钮
  • scripts/prepare-style-dictionary.mjs
    ——添加到
    vendorMeta
    (名称+主页)
  • test/integration/bundle-size.test.ts
    ——仅在必要时增加预算
  • package.json
    ——将同步脚本追加到
    theme:sync
    (若使用同步脚本)

Example projects

示例项目

Example files hardcode theme lists; discover the current set instead of assuming:
bash
undefined
示例文件中硬编码了主题列表;请通过搜索确定当前集合,而非假设:
bash
undefined

Web examples with hardcoded theme arrays / dropdowns

包含硬编码主题数组/下拉菜单的Web示例

rg -l 'VALID_THEMES|LIGHT_THEMES|lightThemes' examples/ rg -l 'THEMES' examples/stackblitz/react examples/stackblitz/vue
rg -l 'VALID_THEMES|LIGHT_THEMES|lightThemes' examples/ rg -l 'THEMES' examples/stackblitz/react examples/stackblitz/vue

Swift example touchpoints

Swift示例关联点

rg -l 'ThemeId|ThemeDefinition' examples/swift-swiftui/

In each hit, add the new variants everywhere an existing variant appears:
`<select>` options, `VALID_THEMES`/`LIGHT_THEMES`/`THEMES` arrays, Swift
`ThemeId.swift` enum cases, `ThemeRegistry.swift` `ThemeDefinition` palettes, and
`ThemeRegistryTests.swift` counts/labels. Files that import from
`@lgtm-hq/turbo-themes-core/tokens` (React hooks, Vue composables, Bootstrap
main.ts) auto-update — skip any file where the grep hit is an import, not a
hardcoded list.
rg -l 'ThemeId|ThemeDefinition' examples/swift-swiftui/

在每个搜索结果中,在现有变体出现的所有位置添加新变体:`<select>`选项、`VALID_THEMES`/`LIGHT_THEMES`/`THEMES`数组、Swift`ThemeId.swift`枚举案例、`ThemeRegistry.swift`中的`ThemeDefinition`调色板,以及`ThemeRegistryTests.swift`中的计数/标签。从`@lgtm-hq/turbo-themes-core/tokens`导入的文件(React hooks、Vue组合式函数、Bootstrap main.ts)会自动更新——跳过任何搜索结果为导入语句而非硬编码列表的文件。

Naming Conventions

命名规范

  • Theme ID: lowercase with hyphens (e.g.,
    rose-pine-moon
    )
  • Variant label (token
    label
    field): full display name including family (e.g., "Gruvbox Dark Hard") — match existing
    .tokens.json
    files
  • Short label (
    themeNames
    in theme-meta.ts): condensed dropdown label (e.g., "Dark Hard", "Moon")
  • Vendor / family: the theme family identifier (e.g.,
    rose-pine
    )
  • 主题ID:小写并使用连字符(例如:
    rose-pine-moon
  • 变体标签(Token的
    label
    字段):包含主题系列的完整显示名称(例如:"Gruvbox Dark Hard")——与现有
    .tokens.json
    文件保持一致
  • 短标签(theme-meta.ts中的
    themeNames
    ):精简的下拉菜单标签(例如:"Dark Hard"、"Moon")
  • 供应商/系列:主题系列标识符(例如:
    rose-pine

Build and Test

构建与测试

bash
uv run lintro chk          # Lint
bun run build              # Core build
bun run examples:build     # Example projects
bun run test               # Unit tests
bun run examples:test      # Example E2E tests
cd apps/site && bun run build   # Site build
cd apps/site && bun run dev     # Visual check
Tip: the
turbo-test
skill runs the full pipeline automatically.
bash
uv run lintro chk          # 代码检查
bun run build              # 核心构建
bun run examples:build     # 示例项目构建
bun run test               # 单元测试
bun run examples:test      # 示例端到端测试
cd apps/site && bun run build   # 站点构建
cd apps/site && bun run dev     # 视觉检查
提示:
turbo-test
技能会自动运行完整流程。

Common Gotchas

常见陷阱

  1. Theme reverts on navigation / wrong label / missing icon: variants missing from
    themeGroups
    /
    themeNames
    /
    themeIcons
    in
    apps/site/src/data/theme-meta.ts
    (the site is data-driven from this file — do not edit BaseLayout.astro for these)
  2. Theme not in dropdown / wrong group:
    VENDOR_FAMILY_MAP
    missing or wrong
  3. Tests fail on theme order: use
    data-theme-id
    attribute lookups, not array indices
  4. Bundle size test fails: increase the budget in bundle-size.test.ts
  5. CI
    Cannot find module './packs/<theme>.synced.js'
    : sync script missing from
    theme:sync
    in package.json
  6. tokens.json shows wrong name/homepage: missing from
    vendorMeta
    in prepare-style-dictionary.mjs
  7. Generated assets outdated: run
    bun run build
    and commit the generated files (theme-selector bundles, tokens.json in core/python/swift)
  8. Type changes: if adding interfaces, update BOTH
    src/themes/types.ts
    AND
    packages/core/src/themes/types.ts
    — separate files kept in sync
  9. Visual regression fails after hero changes: snapshots are generated on Linux CI — run the
    maintenance-generate-snapshots.yml
    workflow
  10. Missing from examples: re-run the example discovery greps and diff the new theme's hits against an existing theme's hits
  1. 导航时主题还原/标签错误/图标缺失:变体未添加到
    apps/site/src/data/theme-meta.ts
    中的
    themeGroups
    /
    themeNames
    /
    themeIcons
    (站点从此文件获取数据——请勿为这些内容编辑BaseLayout.astro)
  2. 主题不在下拉菜单中/分组错误
    VENDOR_FAMILY_MAP
    缺失或错误
  3. 主题顺序导致测试失败:使用
    data-theme-id
    属性查找,而非数组索引
  4. 包大小测试失败:在bundle-size.test.ts中增加预算
  5. CI报错
    Cannot find module './packs/<theme>.synced.js'
    :package.json的
    theme:sync
    中缺少同步脚本
  6. tokens.json显示错误的名称/主页:prepare-style-dictionary.mjs中的
    vendorMeta
    缺失
  7. 生成的资源过期:运行
    bun run build
    并提交生成的文件(theme-selector包、core/python/swift中的tokens.json)
  8. 类型变更:若添加接口,请同时更新
    src/themes/types.ts
    packages/core/src/themes/types.ts
    ——这两个文件需保持同步
  9. 首页修改后视觉回归测试失败:快照在Linux CI上生成——运行
    maintenance-generate-snapshots.yml
    工作流
  10. 未添加到示例中:重新运行示例搜索命令,并将新主题的搜索结果与现有主题的结果对比