Skip to main content
umbraco-example-generator Generate testable example extensions and run them in the Umbraco backoffice
インストールへ移動 Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/umbraco/Umbraco-CMS-Backoffice-Skills --skill umbraco-example-generatorコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... name umbraco-example-generator description Generate testable example extensions and run them in the Umbraco backoffice version 1.0.0 location managed allowed-tools Read, Write, Edit, Glob, Grep, Bash
Umbraco Example Generator
Generate complete, testable example extensions for the Umbraco backoffice and run them using the Umbraco source's dev infrastructure.
When to Use
Creating demonstration extensions
Building testable extension examples
Rapid development with hot reload
Testing extensions without .NET backend
Related Skills
umbraco-unit-testing - Add unit tests to examples
umbraco-mocked-backoffice - E2E testing patterns
umbraco-backoffice - Extension type blueprints
Quick Start
1. Clone Umbraco source (one-time setup)
git clone https://github.com/umbraco/Umbraco-CMS
cd Umbraco-CMS/src/Umbraco.Web.UI.Client
npm install
2. Create your extension folder
my-extension/
├── index.ts # REQUIRED - exports manifests
└── my-element.ts # Your element(s)
3. Create index.ts (exports manifests) import './my-element.js' ;
export const manifests = [
{
type : 'dashboard' ,
alias : 'My.Dashboard' ,
name : 'My Dashboard' ,
element : 'my-element' ,
meta : { label : 'My Dashboard' , pathname : 'my-dashboard' },
conditions : [{ alias : 'Umb.Condition.SectionAlias' , match : 'Umb.Section.Content' }]
}
];
4. Create your element
import { LitElement , html, customElement } from '@umbraco-cms/backoffice/external/lit' ;
@customElement ('my-element' )
export class MyElement extends LitElement {
render ( ) {
return html`<uui-box headline ="Hello" > It works!</uui-box > ` ;
}
}
5. Run it cd Umbraco-CMS/src/Umbraco.Web.UI.Client
VITE_EXAMPLE_PATH=/full/path/to/my-extension VITE_UMBRACO_USE_MSW=on npm run dev
Open http://localhost:5173 - your extension appears in the Content section.
How It Works The Umbraco source (Umbraco-CMS/src/Umbraco.Web.UI.Client) provides two ways to load extensions:
1. Internal Examples (npm run example) Examples placed in the examples/ folder inside the Umbraco source.
cd Umbraco-CMS/src/Umbraco.Web.UI.Client
npm run example
How it works : Sets VITE_EXAMPLE_PATH and imports ./examples/{name}/index.ts
2. External Extensions (absolute VITE_EXAMPLE_PATH) Extensions from any location on your filesystem - perfect for developing packages.
cd Umbraco-CMS/src/Umbraco.Web.UI.Client
VITE_EXAMPLE_PATH=/path/to/your/extension VITE_UMBRACO_USE_MSW=on npm run dev
VITE_UMBRACO_USE_MSW=on mocks the core Umbraco APIs
An absolute VITE_EXAMPLE_PATH is served through Vite's /@fs/ prefix
index.ts imports <VITE_EXAMPLE_PATH>/index.ts and registers its exports with umbExtensionsRegistry
A shared-package resolver maps @umbraco-cms/backoffice, lit and @umbraco-ui/uui to the client's copy (avoids duplicate Lit/UUI)
Absolute-path support (steps 2 & 4) needs a v18 client built with external-example support. When
running this repo's mocked E2E suites, the Playwright harness injects that support into the client
at UMBRACO_CLIENT_PATH automatically and reverts afterwards — see the umbraco-mocked-backoffice skill.
Extension Loading (index.ts)
if (import .meta .env .VITE_EXAMPLE_PATH ) {
const examplePath = import .meta .env .VITE_EXAMPLE_PATH ;
const importPath = examplePath.startsWith ('/' ) ? '/@fs' + examplePath : './' + examplePath;
const js = await import (importPath + '/index.ts' );
if (js) {
Object .keys (js).forEach ((key ) => {
const value = js[key];
if (Array .isArray (value)) {
umbExtensionsRegistry.registerMany (value);
} else if (typeof value === 'object' ) {
umbExtensionsRegistry.register (value);
}
});
}
}
Key point : Your index.ts must export manifests (arrays or objects) that get registered automatically.
Setup
Prerequisites Clone and set up the Umbraco source:
git clone https://github.com/umbraco/Umbraco-CMS
cd Umbraco-CMS/src/Umbraco.Web.UI.Client
npm install
Extension Structure Your extension needs this minimal structure:
my-extension/
├── index.ts # Exports manifests array (REQUIRED)
├── my-element.ts # Your element(s)
├── my-context.ts # Context (if needed)
├── package.json # Optional - for IDE support and tests
├── tsconfig.json # Optional - for IDE support
└── README.md # Documentation
Required: index.ts Your index.ts must export manifests that will be registered:
import './my-dashboard.element.js' ;
export const manifests = [
{
type : 'dashboard' ,
alias : 'My.Dashboard' ,
name : 'My Dashboard' ,
element : 'my-dashboard' ,
weight : 100 ,
meta : {
label : 'My Dashboard' ,
pathname : 'my-dashboard'
},
conditions : [
{
alias : 'Umb.Condition.SectionAlias' ,
match : 'Umb.Section.Content'
}
]
}
];
Optional: package.json (for IDE support) {
"name" : "my-extension" ,
"type" : "module" ,
"devDependencies" : {
"@umbraco-cms/backoffice" : "^18.0.0" ,
"typescript" : "~5.8.0"
}
}
Important : The @umbraco-cms/backoffice dependency is only for IDE TypeScript support. At runtime, imports are resolved from the main Umbraco project.
Running Your Extension
Start the mocked backoffice cd /path/to/Umbraco-CMS/src/Umbraco.Web.UI.Client
VITE_EXAMPLE_PATH=/absolute/path/to/my-extension VITE_UMBRACO_USE_MSW=on npm run dev
Open in browser Navigate to http://localhost:5173 - your extension is loaded automatically.
Hot reload Changes to your extension files trigger hot reload - no restart needed.
Patterns
Basic Element
import { LitElement , html, css, customElement } from '@umbraco-cms/backoffice/external/lit' ;
@customElement ('my-dashboard' )
export class MyDashboardElement extends LitElement {
static override styles = css`
:host {
display : block;
padding : var (--uui-size-layout-1 );
}
` ;
override render ( ) {
return html`
<uui-box headline ="My Extension" >
<p > Running in the mocked backoffice!</p >
</uui-box >
` ;
}
}
declare global {
interface HTMLElementTagNameMap {
'my-dashboard' : MyDashboardElement ;
}
}
Element with Context import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit' ;
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element' ;
import { EXAMPLE_MY_CONTEXT } from './my-context.js' ;
@customElement ('example-my-feature-view' )
export class ExampleMyFeatureViewElement extends UmbLitElement {
@state ()
private _value ?: string ;
constructor ( ) {
super ();
this .consumeContext (EXAMPLE_MY_CONTEXT , (context ) => {
this .observe (context.value , (value ) => {
this ._value = value;
});
});
}
override render ( ) {
return html`
<uui-box headline ="My Feature Example" >
<p > Current value: ${this ._value ?? 'Loading...' } </p >
</uui-box >
` ;
}
}
export default ExampleMyFeatureViewElement ;
declare global {
interface HTMLElementTagNameMap {
'example-my-feature-view' : ExampleMyFeatureViewElement ;
}
}
Context import { UmbContextToken } from '@umbraco-cms/backoffice/context-api' ;
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api' ;
import { UmbStringState } from '@umbraco-cms/backoffice/observable-api' ;
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api' ;
export class ExampleMyContext extends UmbContextBase {
#value = new UmbStringState ('initial' );
readonly value = this .#value.asObservable ();
constructor (host : UmbControllerHost ) {
super (host, EXAMPLE_MY_CONTEXT );
}
setValue (value : string ) {
this .#value.setValue (value);
}
getValue ( ) {
return this .#value.getValue ();
}
public override destroy (): void {
this .#value.destroy ();
super .destroy ();
}
}
export const EXAMPLE_MY_CONTEXT = new UmbContextToken <ExampleMyContext >(
'ExampleMyContext'
);
export { ExampleMyContext as api };
Adding Tests
Unit Tests Add unit tests using @open-wc/testing. See umbraco-unit-testing skill for full setup.
npm install --save-dev @open-wc/testing @web/test-runner @web/test-runner-playwright
E2E Tests (Playwright) Add E2E tests that run against the mocked backoffice. See umbraco-mocked-backoffice skill for patterns.
npm install --save-dev @playwright/test
npx playwright install chromium
Examples
Reference Example Location : ./examples/workspace-feature-toggle/
A complete standalone example demonstrating:
Workspace context with UmbArrayState
Workspace view consuming context
Workspace action executing context methods
Workspace footer app showing summary
38 unit tests + 13 E2E tests
cd examples/workspace-feature-toggle
npm install
npm test
npm run test :e2e
Official Umbraco Examples Location : Umbraco-CMS/src/Umbraco.Web.UI.Client/examples/
27 official examples covering all extension types. Run any example:
cd Umbraco-CMS/src/Umbraco.Web.UI.Client
npm run example
Naming Conventions Item Convention Example Directory kebab-case describing feature workspace-context-counterAlias prefix example.example.workspaceView.counterElement prefix example-example-counter-viewContext token EXAMPLE_ + SCREAMING_CASEEXAMPLE_COUNTER_CONTEXT
Troubleshooting
Extension not appearing
Check index.ts exports a manifests array
Verify the path in VITE_EXAMPLE_PATH is absolute
Check browser console for 📦 Loading external example from: message
Ensure condition matches the section you're viewing
Import errors Imports should use @umbraco-cms/backoffice/*. The Vite plugin resolves these from the main project.
"CustomElementRegistry" already defined Your extension's node_modules is being used instead of the main project's. The external-example-resolver plugin should handle this, but ensure:
You're using VITE_EXAMPLE_PATH=<abs> VITE_UMBRACO_USE_MSW=on npm run dev
Imports use @umbraco-cms/backoffice/* not relative paths to node_modules
Changes not hot reloading Ensure the file is within the path specified by VITE_EXAMPLE_PATH. Only files in that directory tree are watched.