Welcome to the Umbraco Community!

The Umbraco Community is at the heart of the Umbraco ecosystem. It’s built on people coming together to share ideas, help each other, and make Umbraco better every day.

Come see how the Community stays connected, what makes it such a great place to be, and how you can join in and get involved. We always have room for more people to join!

MVP Summit audience.jpg 54610954933_1fd227623f_o (1).jpg Panel speaking in mics at umbraco event Person looking at laptop 52993341606_3b3a6a6991_o.jpg 2025 Group picture 1740139582170.jpg IMG_4217.jpg IMG20251030182101.jpg 2025 Community Teams day at Umbraco HQ DSC04687.jpg DSC05663.jpg MVP getting high five on stage MVPs speaking at MVP Summit 2 MVP waving at MVP Summit MVPs showing off awards IMG20251106141733.jpg 20251204_173423.jpg b6f67a24-17ea-4a21-bc55-65eca97d86ac.jpeg Codegarden 2023 Business Summit - people talking.jpg People high five'ing at Codegarden.jpg Boat ride 2025 Codegarden runners running

Get involved in the community

There's so many ways to get involved in the Umbraco community. 

A person looking into his laptop surrounded by people and light

New here? Welcome! We have a complete newcomer's guide to Umbraco and the Umbraco Community waiting for you.

A woman concentrating and looking down

No matter your interests, skills and time availability, there’s a way for you to participate in the Umbraco community. 

Two people high five'ing

Umbraco Meetups are a great way to engage with the Umbraco community and meet other like-minded people.

See what's happening

Join a meetup or an event near you - see all upcoming Umbraco events here

Blog posts from the Umbraco Community

Explore the latest blog posts from our community. Want to add your future blog posts to the list? Contact us here and let us know!

Umbraco 2-way relations - Umbraco Features You Didn't Know You Needed

Relations in Umbraco: asking the question your picker can't answer You've probably used a Content Picker (or a Multinode Treepicker) to wire content together. A page picks a banner, a landing page picks a set of related articles, a policy picks the older policy it replaces. That gives you one direction for free: open the page, and you can see exactly what it points at. But pickers only answer one question. "What does this page use?" is easy. "What uses this?" is not. The picker property lives on the node that did the picking, not on the node that got picked. If you want to go the other way, your only option is make the pages hierarchical or to loop over every piece of content in the tree and check whether its picker field happens to mention the node you care about. That's exactly the gap Umbraco's Relations are for. A Relation is a first-class, queryable link between two entities that you can walk in either direction via IRelationService: GetByParentId for "what does this point at", GetByChildId for "what points at this". This post walks through a small example project that uses a Relation to answer a question a picker alone can't. The scenario: policies that supersede each other Imagine a "Policy Page" doctype. Editors write a new policy, and pick (via a normal Multinode Treepicker) which older policy or policies it supersedes. That's a completely standard one-way relationship: new policy → picks → old policy. The picker answers "which policies does this one supersede" perfectly well. What it can't answer is the question an editor actually asks when they land on an old policy page: "Has this been superseded, and by what?" Nothing on that old policy's own data points back to the newer one — the pick lives entirely on the other node. Short of scanning every Policy Page in the site for one whose supersedes field happens to mention this node's ID, there's no way to answer it. Why not just use Umbraco's built-in "Related Document" relation? Umbraco ships a built-in relation type for exactly this kind of document-to-document link, aliased umbDocument. It would technically work — except it's a single shared, undifferentiated bucket. Anything in Umbraco (media picker usages, link pickers, whatever else) can write a generic document-to-document reference into it, so a reverse lookup on umbDocument can't reliably tell you "which policy superseded this one" versus any other unrelated reference someone else recorded into the same bucket. The fix is a relation type of your own policySupersedes so a reverse lookup on that alias only ever returns the thing you actually care about. The implementation The example lives in four files. 1. The doctype and the picker. Add a "Policy Page" content type with a bodyText richtext property and a supersedes Multinode Treepicker, filtered so it can only pick other Policy Pages. This is the plain, one-way picker. Nothing special yet. 2. Syncing the picker into a Relation. PolicySupersedesRelationSyncHandler listens for ContentSavedNotification. Every time a Policy Page is saved, it wipes out whatever relations already exist for that node under the policySupersedes alias and rebuilds them from whatever's currently picked: public void Handle(ContentSavedNotification notification) { foreach (IContent content in notification.SavedEntities) { if (content.ContentType.Alias == PolicyPageContentTypeAlias) { SyncSupersedesRelations(content); } } } private void SyncSupersedesRelations(IContent newPolicy) { IRelationType relationType = _relationService.GetRelationTypeByAlias(ExampleConstants.RelationTypeAlias) ?? CreateRelationType(); foreach (IRelation existingRelation in _relationService.GetByParentId(newPolicy.Id, ExampleConstants.RelationTypeAlias)) { _relationService.Delete(existingRelation); } foreach (int supersededPolicyId in GetPickedContentIds(newPolicy)) { var relation = new Relation(newPolicy.Id, supersededPolicyId, relationType) { Comment = $"Marked as superseded on {DateTime.UtcNow:u}", }; _relationService.Save(relation); } } As shown above, you can also add a comment to a relation, which we use to store additional information on when the policy was superseded in our example, which can then be shown again on the Policy page. The relation type itself is created on demand as non-bidirectional, Document-to-Document, and importantly isDependency: true: private IRelationType CreateRelationType() { var relationType = new RelationType( "Policy Supersedes", ExampleConstants.RelationTypeAlias, isBidrectional: false, parentObjectType: Constants.ObjectTypes.Document, childObjectType: Constants.ObjectTypes.Document, isDependency: true, key: null); _relationService.Save(relationType); return relationType; } 3. Wiring it up. Add the notification handler with the standard IComposer boilerplate, nothing Relations-specific. 4. Reading both directions in the view. This is where the payoff shows up. policyPage.cshtml reads the picker property directly for the forward direction, and calls RelationService.GetByChildId for the reverse direction, the direction the picker alone could never give you: var supersededByRelations = RelationService.GetByChildId(Model.Id, ExampleConstants.RelationTypeAlias); @if (supersededByRelations.Any()) { <div style="border: 2px solid red; padding: 1em; margin-bottom: 1em;"> <strong>This policy has been superseded.</strong> <ul> @foreach (var relation in supersededByRelations) { var newerPolicy = ContentQuery.Content(relation.ParentId); if (newerPolicy is not null) { <li> Replaced by <a href="@newerPolicy.Url()">@newerPolicy.Name</a> <br /> <small>@relation.Comment</small> </li> } } </ul> </div> } Open an old policy that's been superseded, and the page now knows it without ever scanning the rest of the tree. The other payoff: you can't delete a still-referenced policy without a warning Setting IsDependency = true on the relation type isn't just documentation, it plugs straight into Umbraco's own dependency checks. Try to delete or unpublish a policy that's still marked as superseded by another one, and the backoffice will warn you it's in use, the same way it would for a media item still referenced by a Content Picker elsewhere. This is the practical version of "what if you need to delete a shared component, but three pages still reference it": with a plain picker, deleting the referenced item is silent and the reference just breaks. With a proper Relation, Umbraco already knows something depends on it and stops you. When to reach for this A picker is enough when you only ever need to ask "what does this content point at", the normal, forward direction. The built-in "Related Document" relation is fine for generic, low-stakes cross-references where you don't care about precision on the reverse lookup. A custom relation type is worth the extra notification-handler code when you need a reverse lookup you can trust "what points at me" and/or you want deletion/unpublish safety for content that's still depended on. Pickers tell you what a page uses. Relations are what let you ask the question in the other direction.

by Bernadet Goey

Quick Tip: Extending the Delivery API's Content Response

A quick look at how to extend Umbraco 17’s Delivery API response with content from elsewhere in the content tree, without building a custom endpoint....

by Johan Reitsma

Notify a Teams channel when you publish content, using Umbraco Automate

Use Umbraco Automate to post a notification to a Microsoft Teams channel whenever content is published, with no custom C#. A step by step walkthrough on Umbraco 17.

by Nathaniel Nunes

Get in contact with us