主题和区块创作技能

用于构建 Discourse 主题和区块组件的 Claude Code 技能库:

:toolbox: 包含内容

主题创作技能 — 涵盖构建 Discourse 主题的完整范围:使用 discourse_theme CLI 进行脚手架搭建、SCSS 架构、视口库、本地化、设置、修饰符、值转换器、图标以及 CSS 变量。图标、变量和转换器的详细参考文件单独提供,可按需加载。SKILL.md

区块创作技能 — 涵盖区块 API 的主题端内容:使用 @block 装饰器编写区块组件、定义参数(args)模式、将区块渲染到可用的核心出口(outlets)、条件判断、容器区块和布局分组,以及将主题翻译和设置集成到区块参数中。SKILL.md

示例主题 — 一个使用区块构建自定义主页的可用主题,展示了出口、条件和布局组合的实际模式。


:jigsaw: 关于区块 API

区块 API 是 Discourse 用于在主题和插件中构建模块化、可组合 UI 组件的新框架。区块是注册到命名出口(如 homepage-blockshero-blockssidebar-discovery)的 Glimmer 组件,并且可以根据路由、用户、视口、站点设置或插件可用性条件性地显示。

该系统的一个关键优势在于区块具有小而专注的作用域以及一致的模式。这使其非常适合 AI 辅助开发:具备区块技能的模型可以在单次操作中完成区块组件的脚手架搭建、将其注册到出口并连接条件。

本仓库中的示例主题展示了一个根据可用插件和内容自适应调整的主页。以下是基本主页的样貌,包含一个英雄区块和一个精选话题列表:

当满足额外条件时(配置了精选标签、Discourse Events 插件已激活且 Discourse Leaderboard 插件可用),额外的区块会被条件性地渲染到布局中:

区块不仅限于主页。示例主题还使用 sidebar-blocks 出口添加主页链接,使用 sidebar-discovery 出口添加特定于分类的侧边栏内容,并在分类页面顶部使用 category-banner 区块:

DevTools 中的区块检查器会在页面上叠加显示出口标签和区块标识符。这使得理解布局结构和调试渲染位置变得非常容易:


:art: 与设计平台 MCP 配合使用

这些技能与设计平台 MCP(如 Penpot 或 Figma MCP)配合效果极佳。连接其中一个后,Claude 可以直接从设计文件中读取组件规范和设计令牌,并使用该技能的约定进行实现。这缩短了设计与代码之间的循环,尤其是在基于结构化设计系统工作时。


:fork_and_knife: 分叉并调整

技能中的一些约定更多是基于偏好而非严格规范,例如 SCSS 文件夹架构。您可以分叉该仓库,并根据自己的工作流和约定调整这些技能。


:speech_balloon: 分享您的成果

请尝试一下并告诉我们您的体验!我们很想知道您如何使用这些技能、用它们构建了什么以及它们存在哪些不足。欢迎提供反馈、修正意见或进行分叉。

会有专门的 Blocks 主题帖吗?还是这就是?

如果是后者,或许可以加一些代码片段?或者 plugin-api.gjs 文件中的内容就是当前的文档?

谢谢。

仍然会有涵盖完整 Blocks API 的文档,包括核心和插件中的实现。关于使用 Blocks 进行主题定制,SKILL.md 应该已经涵盖了所有相关方面。它内容精炼且非常易读。

示例主题中包含了初始化器文件和 Blocks。初始化器文件为每个 BlockOutlet 声明了布局:https://github.com/discourse/discourse-theme-skills/tree/main/javascripts/discourse/api-initializers。

这次真的玩得很开心 :winking_face_with_tongue: …… 和其他 AI 设计工具一样,它在快速原型设计方面表现非常出色,尤其适合那些如果手动草绘会成本过高的创意。

我要求生成一个极具粗野主义风格的编辑首页,并突出展示来自社区的非传统内容。得到了这个布局,其中确实包含了一些非常出色的特色区块构思。最有趣的是,它给这个主题命名为《地狱报》 :grinning_face_with_smiling_eyes:

接着,我尝试了一个一直想探索的风格:日式门户首页,包含密集的区块、柔和的粉彩配色以及大量的小动画…… 非常喜欢这个初步成果:

实际上,最好录一段视频,因为那些微小的动画让整个页面更加生动有趣:

flushy

终于!!!会尽快尝试用它来更新我的实验性主题组件 :smiley:

Elmo Surrounded by Intense Fire

这项工作非常出色且极具创意。如果我们基于这个主题进行分叉和开发,是否需要考虑父主题未来不再随 Discourse 更新的问题?我正在思考该如何处理这种情况。

感谢提供的资源!

感谢 @BrianC

关于父主题保持更新:技能包(skills)紧跟 Discourse 的主题和 Blocks API,因此只要我们要积极使用它们,随着 API 的演进,它们将保持同步。示例主题更多是展示模式的快照。如果您 fork 了它,您就拥有了自己的 fork。但在更新主题时,您可以随时参考技能包或新的示例。

Blocks API 本身的一个核心目标是提供一个稳定且精简的接口,以帮助自定义内容在 Discourse 更新中保持稳健。因此,如果您主要添加自定义块(就像示例主题那样),您实际上已经在一个稳定的环境中操作。需要关注的主要是 outlet 名称或块 API 签名的变更。目前该 API 仍被视为实验性的,因此名称等可能会有变动。

我建议的方法如下:自由地 fork 主题,并将技能包文档作为未来操作方式的动态参考。

我刚刚开始摸索这个(不使用智能代理编码)。

我有一种感觉,把它转换成一个仅控制网站主页的主题组件应该不需要太多工作——例如,一个已经使用 Horizon 主题的网站。这样做会很蠢吗?

此外,我注意到几个问题:

“即将发生的事件”区块未对主题进行排序

它只是按创建日期随意列出事件主题;这非常不实用!!

ask.discourse.com 建议进行此类更改以修复此问题,我可以确认这确实有效(请原谅我缺乏批判性思维):

@bind
async fetchEvents() {
  const count = this.args.count || 5;
  const results = await ajax("discourse-post-event/events");

  if (!results.events?.length) {
    return null;
  }

  const now = new Date();

  // Separate past and future events, then sort ascending by start date
  const upcoming = results.events
    .filter((e) => new Date(e.starts_at) >= now)
    .sort((a, b) => new Date(a.starts_at) - new Date(b.starts_at));

  return upcoming.slice(0, count);
}

“分类横幅”区块未遵循设置

它在所有分类中显示(而不仅仅是指定的分类),并且在导航时似乎不会刷新(只有在页面刷新时才会刷新)。

谢谢你尝试一下 @nathank!目前这仍被视为实验性功能,我们还将对 API 进行一些调整,因此暂时不建议基于它构建主页生成器类型的主题组件。

演示区块只是基础示例。我们即将推出一些 API 更新,以改进数据加载方式。一旦这些更新可用,我会将更改推送到演示主题中的所有区块。

分类横幅区块应在所有分类页面上显示。我认为你提到的分类选择器是用于主页上的精选分类区块的。