Links

Creating your first extension

Learn how to create your first extension for Umbraco.
This guide will help you set up your first extension using vanilla JavaScript or Vite, Typescript, and Lit. It is also part of the prerequisites for Creating a Property Editor and Creating a Custom Dashboard tutorials.

The end result

By the end of this tutorial, we will have a extension up and running with a Web Component. This will be made with Vanilla JavaScript or made and set up with Vite, Typescript, and Lit.
If you want to set up an extension with Vite, Typescript, and Lit, you can skip the section "Extension with Vanilla JavaScript".

App_Plugins

Extensions will go into a folder called App_Plugins. If you don't have this folder, you can create it at the root of your Umbraco project.

Extension with Vanilla JavaScript

We consider it best practice to use at least TypeScript and some kind of build tool to write your extensions. However, since Umbraco's extension system is written entirely in JavaScript, it's possible to create extensions with vanilla JavaScript. For the sake of posterity, we will briefly go through what that looks like:
  • Go to the App_Plugins folder and create a new folder called my-package
  • Navigate into the folder and create a file called umbraco-package.json, and paste the following code. This code sets up a basic package with a dashboard extension:
umbraco-package.json
1
{
2
"$schema": "../../umbraco-package-schema.json",
3
"name": "My.Package",
4
"version": "0.1.0",
5
"extensions": [
6
{
7
"type": "dashboard",
8
"alias": "my.custom.dashboard",
9
"name": "My Dashboard",
10
"js": "/App_Plugins/my-package/dashboard.js",
11
"weight": -1,
12
"meta": {
13
"label": "My Dashboard",
14
"pathname": "my-dashboard"
15
},
16
"conditions": [
17
{
18
"alias": "Umb.Condition.SectionAlias",
19
"match": "Umb.Section.Content"
20
}
21
]
22
}
23
]
24
}
Adding $schema to umbraco-package.json will give you IntelliSense for this file to help you see different options for your package.
  • Next, create a new JavaScript file called dashboard.js and insert the following code:
dashboard.js
1
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
2
import { UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
3
4
const template = document.createElement('template');
5
template.innerHTML = `
6
<style>
7
:host {
8
padding: 20px;
9
display: block;
10
box-sizing: border-box;
11
}
12
</style>
13
14
<uui-box>
15
<h1>Welcome to my dashboard</h1>
16
<p>Example of vanilla JS code</p>
17
18
<uui-button label="Click me" id="clickMe" look="secondary"></uui-button>
19
</uui-box>
20
`;
21
22
export default class MyDashboardElement extends UmbElementMixin(HTMLElement) {
23
/** @type {import('@umbraco-cms/backoffice/notification').UmbNotificationContext} */
24
#notificationContext;
25
26
constructor() {
27
super();
28
this.attachShadow({ mode: 'open' });
29
this.shadowRoot.appendChild(template.content.cloneNode(true));
30
31
this.shadowRoot.getElementById('clickMe').addEventListener('click', this.onClick.bind(this));
32
33
this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => {
34
this.#notificationContext = instance;
35
});
36
}
37
38
onClick = () => {
39
this.#notificationContext?.peek('positive', { data: { headline: 'Hello' } });
40
};
41
}
42
43
customElements.define('my-custom-dashboard', MyDashboardElement);

Running it

Now we have a JavaScript file with a Web Component which gets linked to a Dashboard Extension as part of the Package Manifest JSON.
Press the F5 button in your favorite IDE or run dotnet run in a command line. Then you should be able to see the new dashboard show up in the Content section.
You can read more on how to run Umbraco in the Installation article.

Extension with Vite, Typescript, and Lit

Umbraco recommends building extensions with a setup using TypeScript and a build tool such as Vite. Umbraco uses the library Lit for building web components which we will be using throughout this guide.

Getting Started With Vite

Vite comes with a set of really good presets to get you quickly up and running with libraries and languages. Examples: Lit, Svelte, and vanilla Web Components with both JavaScript and TypeScript. We will use their preset of Lit and TypeScript.
Find a place where you want to keep your source files, this could be the App_Plugins folder in your Umbraco project. And paste the following command:
npm create vite@latest --template lit-ts my-extension
This sets up our new project in a folder named my-extension and creates a package.json file, which includes the necessary packages. Navigate to the new project folder and install the packages using:
npm install
The last thing we need to install now is our Backoffice package. You can install the package using the following command:
npm install -D @umbraco-cms/backoffice
If you see any errors during this process, make sure that you have the right tools installed (Node, .NET, and so on). Also, make sure you have followed the steps on how to Setup Your Development Environment.
Next, create a new file called vite.config.ts and insert the following code:
import { defineConfig } from "vite";
export default defineConfig({
build: {
lib: {
entry: "src/my-element.ts", // your web component source file
formats: ["es"],
},
outDir: "dist", // your web component will be saved in this location
sourcemap: true,
rollupOptions: {
external: [/^@umbraco/],
},
},
});
This alters the Vite default output into a "library mode", where the output is a JavaScript file with the same name as the name attribute in package.json. The name is my-extension if you followed this tutorial with no changes.
You can read more about Vite's build options here.
Navigate to src/my-element.ts, open the file and replace it with the following code:
src/my-element.ts
1
import { LitElement, html, customElement } from "@umbraco-cms/backoffice/external/lit";
2
import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api';
3
import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification';
4
5
@customElement('my-element')
6
export default class MyElement extends UmbElementMixin(LitElement) {
7
#notificationContext?: UmbNotificationContext;
8
9
constructor() {
10
super();
11
this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (_instance) => {
12
this.#notificationContext = _instance;
13
});
14
}
15
16
#onClick = () => {
17
this.#notificationContext?.peek('positive', { data: { message: '#h5yr' } });
18
}
19
20
render() {
21
return html`
22
<uui-box headline="Welcome">
23
<p>A TypeScript Lit Dashboard</p>
24
<uui-button look="primary" label="Click me" @click=${this.#onClick}></uui-button>
25
</uui-box>
26
`;
27
}
28
}
29
30
declare global {
31
interface HTMLElementTagNameMap {
32
'my-element': MyElement;
33
}
34
}
The code above defines a Web Component that contains a button that when clicked will open a notification with a message to the user.
Next, we are going to build the ts file so we can use it in our package:
npm run build
After running the build, you will see a new file in the dist folder with the name my-extension.js. Copy this file and navigate to App_Plugins in your Umbraco project, and create a new folder called my-package. Here we are going to insert the copied file.
Finally, add a file called umbraco-package.json the root of the foldermy-packageand insert the following code:
umbraco-package.json
1
{
2
"$schema": "../../umbraco-package-schema.json",
3
"name": "My Package",
4
"version": "0.1.0",
5
"extensions": [
6
{
7
"type": "dashboard",
8
"alias": "My.Dashboard.MyExtension",
9
"name": "My Dashboard",
10
"js": "/App_Plugins/my-package/my-extension.js",
11
"weight": -1,
12
"meta": {
13
"label": "My Dashboard",
14
"pathname": "my-dashboard"
15
},
16
"conditions": [
17
{
18
"alias": "Umb.Condition.SectionAlias",
19
"match": "Umb.Section.Content"
20
}
21
]
22
}
23
]
24
}

Running it

Now we have a JavaScript file with a Web Component which gets linked to a Dashboard Extension as part of the Package Manifest JSON.
Press the F5 button in your favorite IDE or run dotnet run in a command line. Then you should be able to see the new dashboard show up in the Content section.
You can read more on how to run Umbraco in the Installation article.