
Understanding the Umbraco Backoffice Context API: How Bellissima Extensions Share Data
The first time I built an extension for the new Umbraco backoffice, I got stuck on When I developed an extension for the new Umbraco backoffice for the first time, I ran into a problem that seemed simple enough. I had created a custom workspace view and was only interested in getting the document name being edited. In the old AngularJS backoffice, I'd have injected a service and moved on. In Bellissima, that's not how it works.
The answer was the Context API. I took my time to get used to the system but, once I did, I learned that nearly every part of back-office depends on it, including notifications, windows, the currently using user and what document you're working with. All of it is shared through contexts.
So, here's how I'd explain it to another developer starting out. No code, just the mental model I wish I'd had on day one.
1. A Context Is Just a Shared Object with a Name Tag
Consider the context to be an object that has data and methods as well as a token that identifies it. The token is a name tag. The provider of the context and the consumer of the context both use the same name tag.
This can be understood in practice:
- You don't import a component or call a service directly
- You ask for a context by its token
- The provider and consumer never need to know about each other
I liked this once I saw the benefit. I could replace a provider without touching the extensions using it. And searching the codebase for a token tells you exactly who depends on what.
2. Contexts Travel Up the DOM
Initially, I was intrigued to say the least. In the case that your element needs a context, it sends up a request up the DOM tree until an element responds to the request. If it finds so many responding elements, the closest one is considered as the final answer.
Keeping the following pieces of information in mind:
- Your element can only see contexts provided above it
- Getting a context is async, so your callback fires whenever it's ready
- When your element leaves the DOM, the connection cleans itself up
Why it matters: open two documents side by side and each workspace has its own context. Your extension automatically gets the right one based on where it's rendered. No ID juggling, no mix-ups.
3. Global Contexts Cover the Stuff Everyone Needs
Some contexts sit at the very top of the backoffice, so every extension can reach them. These are global contexts.
The ones I use the most:
- Notifications, for showing a toast after an action
- Modals, for opening dialogs and pickers
- Current user, for checking who's logged in and what they can access
You can also register your own global context through the extension manifest. I've done this for shared things like an API client that several extensions call. It loads once and stays for the whole session, which beats creating the same thing in five places.
4. Workspace Contexts Are Where the Real Data Lives
When you're extending the content editor, you'll be using this context the most. Every workspace (document, media, member, etc) has a workspace context that contains the entity we're editing and performs functionalities such saving.
Here are the things I've found to be useful
- Workspace views, actions, and footer apps all share the same workspace context
- For individual property values, there's a separate property dataset context
- When creating a custom entity type, it is possible to specify your own context for mapping.
This is what creates the native impression associated with custom views. The plugin obtains information from the same source as the Umbraco UI, causing the data to remain consistent.
5. Observe instead of only reading
Here's a mistake I made early: I read a value from a context once and expected it to stay current. It didn't. An editor changed the name, and my view kept showing the old one.
Contexts mostly expose observables, streams that push new values when something changes. You subscribe and react.
Things worth knowing:
- Observe only the exact value you need, not the whole object
- Umbraco's state helpers only fire when a value actually changes
- Observers tied to your element stop on their own when it's removed
Once I switched to observing, the stale data problems went away completely.
Things I'd Tell Myself Earlier
- Use the nearest context that fits. Don't reach for a global one when the workspace context has what you need.
- Observe small pieces of data. It keeps re-renders down.
- Always assume the context isn't there yet. It's async.
- Give your custom tokens clear names. Someone else will have to find them later, and that someone might be you.
- One context, one job. Big catch-all contexts get messy fast.
- Don't hang on to a context after your element is gone.
Wrapping Up
The Context API felt like extra ceremony when I started. Now I see it as the thing that keeps Bellissima from turning into a pile of extensions poking at each other.
The shift is simple. Cease querying “where does this data come from” and begin inquiring “what context made it available?”. The acceptance of this one question would solve virtually all the queries you come across.
Related Blogs

Most enterprises don't run one website. They have portfolios, regional stores,…
Read More
Umbraco makes it easy to ship fast. It also makes it easy to end up with business logic…
Read More
Most agencies won't give you a straight answer. They'll say, "it depends" and leave you…
Read More