用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/umbraco/Umbraco-CMS-Backoffice-Skills --skill umbraco-tree命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
基于 SOC 职业分类
| name | umbraco-tree |
| description | Implement trees in Umbraco backoffice using official docs |
| version | 1.2.0 |
| location | managed |
| allowed-tools | Read, Write, Edit, WebFetch |
A tree in Umbraco is a hierarchical structure of nodes registered in the Backoffice extension registry. Trees display organized content hierarchies and can be rendered anywhere in the Backoffice using the <umb-tree /> element. They require a data source implementation to fetch root items, children, and ancestors.
Always fetch the latest docs before implementing:
Trees and workspaces are tightly coupled. When using kind: 'default' tree items:
Tree items REQUIRE workspaces - Clicking a tree item navigates to a workspace for that entity type. Without a workspace registered for the entityType, clicking causes "forever loading"
Workspaces must be kind: 'routable' - For proper tree item selection state and navigation between items of the same type, use kind: 'routable' workspaces (not kind: 'default')
Entity types link trees to workspaces - The entityType in your tree item data must match the entityType in your workspace manifest
When implementing trees with clickable items, also reference the umbraco-workspace skill.
Modern trees use 2-3 files:
my-tree/
├── manifest.ts # Registers repository and tree
├── tree.repository.ts # Repository + inline data source
└── types.ts # Type definitions (optional)
The Umbraco source includes a working example:
Location: /Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/tree/
This example demonstrates a complete custom tree with data source, repository, and menu integration. Study this for production patterns.
If you need to explain these foundational concepts when implementing trees, reference these skills:
Repository Pattern: When implementing tree data sources, repositories, data fetching, or CRUD operations
umbraco-repository-patternContext API: When implementing repository contexts or explaining how repositories connect to UI components
umbraco-context-apiState Management: When implementing reactive tree updates, observables, or managing tree state
umbraco-state-managementmanifest.ts, tree.repository.ts (with inline data source)tree.store.ts (removed in v18), separate tree.data-source.ts (can inline)umbraco-workspace skill)To show tree items at root level (without a parent folder), use hideTreeRoot: true on the menuItem manifest:
// CORRECT - hideTreeRoot on menuItem
{
type: 'menuItem',
kind: 'tree',
alias: 'My.MenuItem.Tree',
meta: {
treeAlias: 'My.Tree',
menus: ['My.Menu'],
hideTreeRoot: true, // Shows items at root level
},
}
// WRONG - hideTreeRoot on tree (has no effect)
{
type: 'tree',
meta: {
hideTreeRoot: true, // This does nothing!
},
}
export const manifests: UmbExtensionManifest[] = [
// Repository
{
type: 'repository',
alias: 'My.Tree.Repository',
name: 'My Tree Repository',
api: () => import('./tree.repository.js'),
},
// Tree
{
type: 'tree',
kind: 'default',
alias: 'My.Tree',
name: 'My Tree',
meta: {
repositoryAlias: 'My.Tree.Repository',
},
},
// Tree Items - use kind: 'default' when workspaces exist
{
type: 'treeItem',
kind: 'default',
alias: 'My.TreeItem',
name: 'My Tree Item',
forEntityTypes: ['my-entity'],
},
// MenuItem - hideTreeRoot here
{
type: 'menuItem',
kind: 'tree',
alias: 'My.MenuItem.Tree',
meta: {
treeAlias: 'My.Tree',
menus: ['My.Menu'],
hideTreeRoot: ,
},
},
];
Modern simplified pattern - everything in one file:
import { UmbTreeRepositoryBase, UmbTreeServerDataSourceBase } from '@umbraco-cms/backoffice/tree';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
import type { MyTreeItemModel, MyTreeRootModel } from './types.js';
import { MY_ROOT_ENTITY_TYPE, MY_ENTITY_TYPE } from './entity.js';
// Data source as simple class using helper base
class MyTreeDataSource extends UmbTreeServerDataSourceBase<any, MyTreeItemModel> {
constructor(host: UmbControllerHost) {
super(host, {
getRootItems: async (args) => {
// Fetch from API or return mock data
const items: MyTreeItemModel[] = [
{
unique: 'item-1',
parent: { unique: , : },
: ,
: ,
: ,
: ,
: ,
},
];
{ : { items, : items. } };
},
: (args) => {
{ : { : [], : } };
},
: (args) => {
{ : [] };
},
: item,
});
}
}
<, >
{
() {
(host, );
}
() {
: = {
: ,
: ,
: ,
: ,
: ,
};
{ data };
}
}
{ api };
Why this is simpler:
UmbTreeServerDataSourceBase helper (pass functions, not methods)For complex trees with API calls, you can still separate into different files, but it's not required.
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.
Run tests from skill examples and generate a report (project)
Validate links and references in SKILL.md files using deterministic scripts
Umbraco backoffice extension customisation - complete working examples showing how extension types combine