Add a new module to the core package (src/packages/core/). Use when adding shared UI framework infrastructure that all packages can use — e.g., a new extension system feature, a new utility, a new shared component pattern, a new picker, or a new workspace primitive. Core modules are imported as @umbraco-cms/backoffice/{module-name}. Also use when the user says things like "add a module to core", "create a new core feature", or "add shared infrastructure".
Add a new module to the core package (src/packages/core/).
picker, sorter, entity-flag, modal, section)picker, sorter, entity-flag)create-packageCore modules should not implement CMS-specific features. They provide the building blocks that CMS feature packages use.
src/packages/core/{module-name}/
├── index.ts # Public API exports
├── manifests.ts # Extension registrations (if any)
├── constants.ts # Module constants
└── types.ts # Module types
The public API. Only export what other packages need:
export * from './constants.js';
export type * from './types.js';
Use export type * for type-only exports.
Extension registrations for this module:
export const manifests: Array<UmbExtensionManifest> = [
// Extension registrations
];
If the module has no extensions (pure utility), export an empty array.
// Aliases, context tokens, entity types
// Type definitions, interfaces, meta types
Add the module's manifests to src/packages/core/manifests.ts:
import { manifests as {moduleName}Manifests } from './{module-name}/manifests.js';
// In the manifests array:
...{moduleName}Manifests,
The imports are in alphabetical order — insert in the right position.
Add the module to the entry object in src/packages/core/vite.config.ts:
'{module-name}/index': './{module-name}/index.ts',
The entries are in alphabetical order — insert in the right position. This tells Vite to build the module as a separate entry point.
Add to the exports field in the root package.json (src/Umbraco.Web.UI.Client/package.json):
"./{module-name}": "./dist-cms/packages/core/{module-name}/index.js"
This enables imports like @umbraco-cms/backoffice/{module-name}.
npm run generate:tsconfig
This updates tsconfig.json paths so the new module resolves correctly in TypeScript.
After registration, other packages import from the module like:
import { MyThing } from '@umbraco-cms/backoffice/{module-name}';
import type { MyType } from '@umbraco-cms/backoffice/{module-name}';
src/packages/core/culture/ — repository + components, minimal surfacesrc/packages/core/entity-action/ — kinds, base classes, shared elementsrc/packages/core/repository/ — base classes for the data access patternsrc/packages/core/index.ts exports only the public APImanifests.ts exports extension registrations (or empty array)constants.ts and types.ts createdsrc/packages/core/manifests.ts (alphabetical order)src/packages/core/vite.config.ts (alphabetical order)package.jsonnpm run generate:tsconfig executednpm run compile