Umbraco Extension Registry
What is it?
The Extension Registry is the core system managing all Umbraco backoffice UI elements - almost any UI in the Backoffice is an extension managed by the Extension Registry. The registry allows developers to dynamically add, remove, or modify extensions at runtime using umbExtensionsRegistry . Developers have the same possibilities as Umbraco HQ, meaning you can change almost everything that is by default present in Umbraco.
Documentation
Always fetch the latest docs before implementing:
-
Main docs: https://docs.umbraco.com/umbraco-cms/customizing/extending-overview/extension-registry
-
Register Extensions: https://docs.umbraco.com/umbraco-cms/customizing/extending-overview/extension-registry/register-extensions
-
Replace/Exclude: https://docs.umbraco.com/umbraco-cms/customizing/extending-overview/extension-registry/replace-exclude-or-unregister
-
Extension Manifest: https://docs.umbraco.com/umbraco-cms/customizing/extending-overview/extension-registry/extension-manifest
-
Foundation: https://docs.umbraco.com/umbraco-cms/customizing/foundation
Workflow
-
Fetch docs - Use WebFetch on the URLs above
-
Ask questions - Register, exclude, or replace? Runtime or static? Conditions needed?
-
Generate code - Implement registry operations based on latest docs
-
Explain - Show what was created and how extensions are managed
Minimal Examples
Register Extension (Runtime)
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
const manifest = { type: 'dashboard', alias: 'My.Dashboard', name: 'My Dashboard', element: () => import('./dashboard.element.js'), meta: { label: 'My Dashboard', pathname: 'my-dashboard' } };
umbExtensionsRegistry.register(manifest);
Exclude Extension
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// Permanently hide an extension umbExtensionsRegistry.exclude('Umb.WorkspaceAction.Document.SaveAndPreview');
Unregister Extension
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// Remove extension from registry (can be re-registered) umbExtensionsRegistry.unregister('My.WorkspaceAction.AutoFillWithUnicorns');
Replace Extension (Overwrites)
const manifest = { type: 'workspaceAction', alias: 'My.WorkspaceAction.ExternalPreview', name: 'My Custom Preview', overwrites: 'Umb.WorkspaceAction.Document.SaveAndPreview', element: () => import('./custom-preview.element.js'), // ... rest of manifest };
umbExtensionsRegistry.register(manifest);
Replace Multiple Extensions
const manifest = { type: 'workspaceAction', alias: 'My.CustomSave', name: 'My Custom Save', overwrites: [ 'Umb.WorkspaceAction.Document.SaveAndPreview', 'Umb.WorkspaceAction.Document.Save' ], // ... rest of manifest };
umbExtensionsRegistry.register(manifest);
Entry Point Registration
// entrypoint.ts import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
export const onInit = (host: UmbEntryPointOnInitArgs) => { // Exclude default dashboard umbExtensionsRegistry.exclude('Umb.Dashboard.UmbracoNews');
// Register custom dashboard umbExtensionsRegistry.register({ type: 'dashboard', alias: 'My.CustomDashboard', name: 'Custom Dashboard', element: () => import('./custom-dashboard.element.js'), meta: { label: 'Welcome', pathname: 'welcome' }, conditions: [ { alias: 'Umb.Condition.SectionAlias', match: 'Umb.Section.Content' } ] }); };
Dynamic Registration from Server Data
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
async function registerDynamicDashboards() { // Fetch configuration from server const response = await fetch('/api/dashboard-config'); const dashboards = await response.json();
// Register each dashboard dynamically dashboards.forEach(config => { umbExtensionsRegistry.register({ type: 'dashboard', alias: config.alias, name: config.name, element: () => import(config.elementPath), meta: { label: config.label, pathname: config.pathname } }); }); }
Conditional Registration
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// Register extension only if condition is met if (userIsAdmin) { umbExtensionsRegistry.register({ type: 'dashboard', alias: 'My.AdminDashboard', name: 'Admin Dashboard', element: () => import('./admin-dashboard.element.js'), meta: { label: 'Admin', pathname: 'admin' } }); }
Batch Operations
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
// Exclude multiple extensions const extensionsToHide = [ 'Umb.Dashboard.UmbracoNews', 'Umb.Dashboard.RedirectManagement', ];
extensionsToHide.forEach(alias => { umbExtensionsRegistry.exclude(alias); });
// Register multiple extensions const myExtensions = [ { type: 'dashboard', alias: 'My.Dashboard1', /* ... / }, { type: 'dashboard', alias: 'My.Dashboard2', / ... */ }, ];
myExtensions.forEach(manifest => { umbExtensionsRegistry.register(manifest); });
View Registered Extensions
Navigate to: Settings > Extensions Insights in the backoffice to see all registered extensions.
Key Concepts
umbExtensionsRegistry: Central registry for managing extensions
register(): Add new extension at runtime
exclude(): Permanently hide extension (never displayed)
unregister(): Remove extension from registry (can be re-registered)
overwrites: Replace existing extension(s) with custom implementation
Runtime vs Static:
-
Static: Use umbraco-package.json for most extensions
-
Runtime: Use umbExtensionsRegistry for dynamic/conditional registration
Entry Point: Common place to execute registry operations during startup
Extension Insights: View all registered extensions at Settings > Extensions Insights
Use Cases:
-
Hide default Umbraco features
-
Register extensions based on server data
-
Replace built-in actions with custom logic
-
Conditionally enable features
-
Dynamic dashboard registration
Sources
-
Extension Registry | Umbraco CMS
-
Register an Extension | Umbraco CMS
-
Replace, Exclude or Unregister | Umbraco CMS
That's it! Always fetch fresh docs, keep examples minimal, generate complete working code.