跳到正文
cccskills
免费在 GitHub 公开中文介绍

compose-atoms

将大型功能拆分为按能力划分的 React 部件,让不同页面按需组合;并把数据、界面状态和操作放到对应部件中,减少轻量页面加载无用依赖。

原文查看原文说明

Use for splitting heavy domains into capabilities (原子组件) across page, portal, share or micro-app hosts, sinking state (状态下沉) and replacing mode/readOnly flags. Simple component splits: react.

lobehub/lobehub星标 83,502(GitHub 83,502 + cccskills 0)

实测评分 未实测

查看安装方法

适用场景

  • 在多个页面共用功能
  • 避免轻量页面加载无用功能
  • 按能力安置状态与操作
  • 整理 mode 或 readOnly 分支

中文介绍

功能

这份设计指南说明如何把大型功能拆分为按能力划分的部件,让页面、门户、共享界面或微应用按需组合。拆分的目标不是单纯把视觉界面切成更小的文件,而是让每个部件都成为使用方可以不加载的单元。数据获取、显示用数据、临时界面状态和更新操作应放在需要它们的部件中;组装层负责布局,并选择要加载哪些部件。这种结构有助于避免轻量页面引入自己不会使用的功能依赖。

适用场景

同一功能需要出现在多个地方,例如完整页面和公开分享页面,而且不同使用方需要不同的编辑或操作能力时,适合采用这种方式。新增功能不断带来 mode 或 readOnly 条件分支,或希望把状态从页面组装层移走时也可以参考。若只是拆分单个页面中的简单组件,请使用 react。

使用示例

  • “请把这项功能拆成按能力划分的部件,供普通页面和公开页面使用,并说明如何组装。”
  • “请移除只读标记,让只有需要编辑功能的页面才加载相关部件。”
  • “请把数据获取和临时状态移到合适的部件中。”

注意事项

拆分后,请检查轻量使用方的导入关系,确认不会加载不需要的模块。

本介绍由 AI(OpenAI Codex)根据公开的 SKILL.md 撰写。准确的规格请查看下方原文。

文档检查

AI 根据 SKILL.md 的内容检查了需要注意的操作和使用前提。评分只依据实际运行的结果(实测对比)。

安全性发送数据、删除文件、执行命令等是否有说明
A良好资料所述操作是设计和导入关系检查,不涉及删除或对外发送。
安装难易度所需工具和 API 密钥是否少且有说明
A良好这是 React 设计指南,未说明需要额外工具或认证信息。

不计入评分。 由 AI(OpenAI Codex)于 2026年10月26日 评估。仅供参考,安装前请同时查看原文。

如果您认为评估有误,请申请复核

请写明哪一项有误以及原因。无需登录。我们会对照 SKILL.md 重新评估,并在此处更新结果。

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

包含的文件(1)

  • SKILL.md10.3 KB

SKILL.md(原文)

安装前可以查看交给 AI 代理的指令内容。

Compose Atoms

A heavy domain is a kit, not a viewer with modes. Each host is an import list. An atom owns the data, actions, and dependencies of one capability. The assembler only chooses what to mount.

This is a module-graph split. Hiding UI does not drop a module. A host that never imports a file is the only host that does not ship it.

Do not use this skill to slice one component into smaller files. That is react.

When

The folder is a product surface (Conversation, Acceptance, Document, Verify, Task, …) and at least one of these is true:

  • One entry owns read + write + workflow + host integration.
  • A second host already exists or is the next change (page, portal, share, mobile, popup, micro-app).
  • The next feature is another boolean / mode / variant on the fat tree.
  • Reusing a header, list, or card would import trays, stores, or chat.

If the file is large but has one capability and one host, stop. Use react.

Grain

An atom is the smallest unit a host is allowed not to mount.

Ask, for every chunk: would any host ship the rest and skip this? If yes, it is an atom. If no, it stays inside its parent.

That grain is coarser than a visual section and finer than the whole page.

Too coarseRight grainToo fine
One Viewer with readOnlyIdentity, goal, list, decision, …Every badge, row, and icon as a public export
Chat as a single importList, composer, intervention, …Every message sub-row the page then rewires
Document as editor + every panelCanvas, header, comments as omittedInternal toolbar buttons

A workflow (focus review, thread, publish) is one atom to hosts that skip the whole mode. Inside it, keep splitting only if a host would mount a piece of that workflow alone.

Sink State

The split is worthless if the assembler still holds the domain state. Imports follow the hook. A useStore / useX / handleAccept left on the page keeps that module (and everything it imports) on every host that mounts the page.

Sink everything the atom needs into the atom:

Sinks into the atomStays on the assembler
Resource fetchThe record id / scope identity
Derived view model (counts, labels, scope)Which atoms are mounted (the import list)
Transient UI (filter, collapse, pending)Host layout state (focused vs overview, rail)
Mutation handlers and their stores/modalsHost seams (provider value the runtime owns)
// wrong — visual split, state still on the page
const Page = () => {
  const { data, mutate } = useX(id);
  const [filter, setFilter] = useState('all');
  const accept = () => void mutate(...);
  return (
    <>
      <Identity data={data} />
      <List data={data} filter={filter} onFilter={setFilter} />
      <DecisionBar onAccept={accept} />
    </>
  );
};

// right — each atom reads and acts; page only assembles
const Page = () => (
  <Scope id={id}>
    <Identity />
    <List />
    <Decision />
  </Scope>
);

Do not lift "to fetch once" or "so siblings share data". Two atoms calling the same SWR hook share the cache by key. Sibling writes go through that cache (or a store slice the write atom imports), not through page useState.

Lift only when the state is the assembler's job: which workflow is on screen, whether a rail is open. If a value is used to render or mutate one capability, it belongs in that capability.

Kit

PieceOwnsMust not own
Domain primitiveTypes, predicates, formattersReact, stores, services
Data accessOne resource, one fileSibling list / infinite / document hooks
Read atomPresent + local UI state + its own fetchMutations, trays, owner services, host stores
Write atomOne mutation and its UIPage layout, unrelated writes
Workflow atomA mode assembled from other atomsBecoming the only entry other hosts can import
Domain slotReactNode hole for another same-domain atomA callback whose implementation lives in this file
Host seamOptional host-provided UI, null by defaultA fallback that imports the host graph
AssemblerLayout + the import listDomain actions; domain fetch except local chrome

A visual block that both reads and writes is a read atom + a write atom, joined by a domain slot.

Two seam types — do not mix them:

  • Domain slot — same feature, optional capability (editSlot, toolbar). The host imports the write atom and passes it in.
  • Host seam — only some runtimes can resolve it (chat store, topic drawer, Electron). Context default is null. The micro-app / share page never imports the provider value. See split-micro-app for the runtime cut.

Ownership

State and imports live in the atom that needs them.

  • Read atoms call the isolated resource hook. Filter / collapse / expand stay in the atom.
  • Write atoms call the same hook, then mutate. They import their own modals and services. They return null when the record is not writable.
  • Workflow atoms compose other atoms. They still do not become the light host's entry.
  • Assemblers do not fetch in order to push props down. Chrome unique to that host (a title in a shell header) may read the hook.
  • Scope context carries identity (id, embedded). It does not carry actions, stores, or modal openers.

Several atoms calling the same SWR hook is expected. SWR dedupes on key. Do not lift data to the assembler "to fetch once".

The shared read hook is its own file. A light host imports that file, never a hooks.ts / store barrel that also exports list, document, or send-message.

// any host:
import { useX } from '@/features/Domain/useX';

// never from a light host:
import { useX } from '@/features/Domain/hooks';
import { DomainViewer } from '@/features/Domain';

A flag that only changes behavior of code already in the atom is fine. A flag whose purpose is to skip importing another module is not — that module is a slot or a sibling the assembler omits.

dynamic(() => import(...)) only helps when no static import of that module remains on the light graph.

Assembler

A host is its import list.

// light host — deep imports only
<Scope id={id}>
  <ReadA />
  <ReadB />
</Scope>

// full host — same reads, write atoms in slots, workflows as siblings
<ReadA extra={<WriteA />} />
<ReadB toolbar={<WriteB />} />
<Workflow />
<WriteC />

Route / portal files compose host skeleton (providers, host seams). Do not add a wrapper page whose only job is to sit between the route and the assembler.

The feature barrel may export the full assembler for in-app use. Light hosts must not import that barrel.

Procedure

  1. List hosts (page, portal, share, mobile, popup, micro-app — include the next one).
  2. List capabilities as verbs (view identity, edit field, decide, open host thing). Map host → verbs.
  3. Set grain: each verb a host can skip is an atom. Group the rest under a parent.
  4. Extract primitives and the isolated read hook first.
  5. Extract read atoms. Optional same-domain capabilities become ReactNode slots, not callbacks that close over write modules.
  6. Extract each write / workflow atom into its own file. Heavy deps stay in that file.
  7. Sink state. Move fetch, view-model, transient UI, and handlers out of the assembler. If the page still calls a domain hook to feed props, the split is not done.
  8. Rewrite every host as an import list plus layout. Delete readOnly / isPublic / mode / variant on the fat tree.
  9. Point light hosts at atoms by deep path.
  10. Prove the cut. Grep the light entry's import tree, or trace a module the light host must not ship. A missing button is not proof.
# example: light host must not import a write atom
WORKBENCH_TRACE_MODULE=features/Acceptance/Viewer/Review/AcceptanceDecision bun run build:rr

If the light assembler appears on the importer chain, a static import still exists — usually a barrel, a leftover flag, or actions left on the page.

Example

src/features/Acceptance/Viewer/ is one application of this kit, not the template to copy file-for-file.

HostMounts
In-app Acceptance/index.tsxIdentity, goal, inventory, decision, focus workflow, ledger + write slots
Workbench public detailIdentity, goal, inventory, discussion with sign-in guidance
PortalFull assembler + OriginConversationProvider

Read AcceptanceGoal (read + editSlot) and AcceptanceGoalEdit (write) for the slot cut. Read originConversation.tsx for a host seam. Read workbench AcceptanceDetail.tsx for a light assembler.

Related skills

  • react: single-surface boundaries, styling, memoization.
  • split-micro-app: worker / SSR / gateway / stubs. This skill is how the shared UI is cut afterwards.
  • spa-routes: route files stay thin assemblers.
  • data-fetching-architecture: how the isolated hook fetches, not where a host may import it from.
  • zustand: narrow selectors inside an atom; do not put the whole store on scope context.

评价

还没有评价。欢迎分享你的使用感受。

评论

无需登录即可发表。欢迎分享使用感受、提问,或说明在哪些环境下无法运行。

还没有评论。来写第一条吧。

提交后会立即公开。请勿填写邮箱、电话等个人信息。URL 最多 2 个。

0 / 1000 字

此表单受 reCAPTCHA 保护,适用 Google 的隐私权政策和服务条款。

同一仓库的技能

acceptance

免费有简介

通过实际操作产品验证交付内容,记录用户可查看的证据,并发布验收报告。可检查已有验证计划或创建检查项,选择合适的操作界面,并使用 `lh` CLI 发布结果。

  • 实际检查更改后的产品行为
  • 收集截图或其他验证证据
  • 编写验证计划和报告
lobehub/lobehub8.4万2026年10月26日 更新

add-model-provider

免费有简介

本技能指导在 LobeHub 中接入 AI 模型提供商,涵盖运行时、模型信息、设置、品牌展示、文档和验收,并帮助判断新增模型是否需要新的提供商集成。

  • 为 LobeHub 接入新的 AI 模型提供商
  • 更新提供商设置说明或介绍
  • 判断添加模型是否需要新的提供商集成
lobehub/lobehub8.4万2026年10月26日 更新

add-setting-env

免费有简介

本技能指导如何用服务器端环境变量设置用户偏好默认值,涵盖变量校验、服务器配置、写入用户状态,以及更新 `.env.example` 和自托管文档。

  • 通过环境变量设置用户偏好默认值
  • 将设置接入服务器配置和用户状态
  • 更新环境变量示例及文档
lobehub/lobehub8.4万2026年10月26日 更新

agent-runtime-hooks

免费有简介

说明如何在智能体执行步骤、工具调用、人工审批、上下文压缩和子智能体调用时注册钩子。钩子可观察事件、模拟本地工具结果,也可通过 Webhook 按配置策略允许或拒绝工具调用。

  • 记录智能体步骤和错误
  • 测试时模拟工具结果
  • 通过 Webhook 允许或拒绝工具调用
lobehub/lobehub8.4万2026年10月26日 更新

agent-signal

免费有简介

此技能用于为智能体设计事件驱动的后台工作流,划分来源、信号、动作和策略的职责,并处理异步交接、去重、执行范围、完成记录与运行观测。

  • 添加事件触发的后台任务
  • 将工作移出对话请求
  • 防止动作重复执行
lobehub/lobehub8.4万2026年10月26日 更新

agent-testing-bot

免费有简介

本技能在 macOS 桌面聊天应用中测试机器人频道:打开应用、进入频道或联系人、发送消息、等待回复并截图。支持 Discord、Slack、Telegram、微信、飞书和 QQ;iMessage 使用 BlueBubbles 桥接。

  • 检查真实 Discord 频道中的机器人回复
  • 测试 Slack 或 Telegram 的对话流程
  • 记录 macOS 应用中的操作结果
lobehub/lobehub8.4万2026年10月26日 更新

查看 lobehub 的全部技能

报告此技能的问题