Upgrade v13 to v14 and IDashboard

I started upgrade from v13 to v14, and stuck at missing Umbraco.Cms.Core.Dashboards and IDashboard. Have few classes with dashboard definitions, and can’t find any info on breaking change with v14. Interestingly, there’s no docs for v14, only v15!

v15 shows how to create custom dashboards as a web component with bunch front end stuff (vite, typescript - Creating a Custom Dashboard | Umbraco CMS) which i would really like to avoid if possible. Is there a way to define custom dashboard location (mine is simple static HTML file) with just backend c# code, or even some Json?
Creating a full blows vite/ts project just to say “use mydashboard.html” seems like a big overkill and overengineering.

Example of my dashboard:

[Weight(10)]
public class CrmDashboard : IDashboard
{
public string[] Sections => [ Constants.Applications.Content ]
public IAccessRule[] AccessRules => Array.Empty<IAccessRule>();
public string? Alias => "CRM";
public string View => "/App_Plugins/crm/index.html"
}

Hi @hudo,

The reason there are no v14 docs is that v14 reached end-of-support on May 30, 2025.

(See Umbraco’s page on the long-term support dates, to note v15 reached end-of-support on November 14, 2025)

In terms of upgrades, you can go straight from v13 to v16, (and/or v17 once it’s released on November 27, 2025).

As for an answer to your issue with the dashboards, there is a package available for v15 that enables you to register a dashboard in C# and use a Razor view to render the dashboard.

As for the “overkill and overengineering” of a Vite/TS project, I hear you, as do others. The arguments and explanations have been made several times on the forum, if you wanted to read up on these.

With the new (current) backoffice, it’s pure JavaScript/WebComponents, in which you can develop these however you like. The main reason for the focus on Vite/TS is that once you get into more advanced scenarios, those tools become very useful, (for type-safety/intellisense, bundling/minification, package builds, etc), so it’s a steeper learning curve upfront, which will hopefully pay-off later. Of course, any suggestions on ways to simplify this are very welcome.

1 Like

Thank you very much for your response! I will try just going to v16 then. I thought I have to go to the closest LTS ( Upgrade Details | Umbraco CMS ), but now realise v14 is not LTS but STS, so my mistake.
Will also try Simple Dashboard package.

Btw, is there anything specific to be aware of when going from v13 to v16? Docs mentions v14, probably because that was the latest version then…
I have few custom built stuff, like my notification handlers (registered with IComposer class, example builder.AddNotificationHandler<ContentSavingNotification, CustomContentSavingNotificationHandler>();and bunch of controllers inheriting from SurfaceController

Also see macros are removed, and I used it for member register/login partial views, will have to build that part again probably.

Apart from that any custom extensions will need to be redeveloped (from AngularJS to WebComponents), the rest is mostly the breaking-changes to consider, which there have been too many for me to list here, it’s all on the docs (per major version):

One of the aims for v17 is to have a more condensed guide on how to go from LTS to LTS (v13 to v17). A community documentation team has recently started to help tackle these types of concerns.

1 Like

Tried upgrading to V16.2, but when I removed all my custom code (i reference models, and there’s a breaking change with auto generated model classes so doesn’t build until I probably regenerate them) and started the app, update thinks I am on v16 (should be v13) and needs to update to 16.2. There’s also some Db error also.
Wonder why it thinks i am on v16…

Logs

{“@t”:“2025-09-09T10:53:03.6120382Z”,“@mt”:“Plan {PlanName} failed at step {TargetState}”,“@l”:“Error”,“@x”:“System.ArgumentException: LockObject with id=-345 does not exist.\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.SqlServerDistributedLock.ObtainWriteLock()\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.SqlServerDistributedLock..ctor(SqlServerDistributedLockingMechanism parent, Int32 lockId, DistributedLockType lockType, TimeSpan timeout)\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.WriteLock(Int32 lockId, Nullable1 obtainLockTimeout)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.ObtainWriteLock(Int32 lockId, Nullable1 timeout)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.LockInner(Guid instanceId, Dictionary2& locks, HashSet1& locksSet, Action2 obtainLock, Nullable1 timeout, Int32 lockId)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.EagerWriteLockInner(Guid instanceId, Nullable1 timeout, Int32 lockIds)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.WriteLock(Guid instanceId, Nullable1 timeout, Int32 lockIds)\r\n at Umbraco.Cms.Core.Scoping.CoreScope.WriteLock(Int32 lockIds)\r\n at Umbraco.Cms.Core.Services.DocumentUrlService.CreateOrUpdateUrlSegmentsAsync(IEnumerable1 documentsEnumerable)\r\n at Umbraco.Cms.Core.Services.DocumentUrlService.RebuildAllUrlsAsync()\r\n at Umbraco.Cms.Core.Services.DocumentUrlService.InitAsync(Boolean forceEmpty, CancellationToken cancellationToken)\r\n at Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_0_0.RebuildDocumentUrls.Migrate()\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationBase.MigrateAsync()\r\n at Umbraco.Cms.Infrastructure.Migrations.AsyncMigrationBase.RunAsync()\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor.RunMigrationAsync(Type migrationType, MigrationContext context)\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor.RunScopedMigrationAsync(Transition transition, MigrationPlan plan)\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor.RunMigrationPlanAsync(MigrationPlan plan, String fromState)“,”@tr":“8977f91429d828767db78397502d7e67”,“@sp”:“36f1d82b448b1005”,“PlanName”:“Umbraco.Core”,“TargetState”:“{3FE0FA2D-CF4F-4892-BA8D-E97D06E028DC}”,“SourceContext”:“Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor”,“ActionId”:“7f2bad3e-cfb8-47ce-8250-9edccd883dfc”,“ActionName”:“Umbraco.Cms.Api.Management.Controllers.Upgrade.AuthorizeUpgradeController.Authorize (Umbraco.Cms.Api.Management)”,“RequestId”:“4000007b-0000-fa00-b63f-84710c7967bb”,“RequestPath”:“/umbraco/management/api/v1/upgrade/authorize”,“ProcessId”:19900,“ProcessName”:“iisexpress”,“ThreadId”:37,“ApplicationId”:“0a353b397f57dc2e27e468fd727e71af0c5d5acc”,“MachineName”:“WIN11VM”,“Log4NetLevel”:“ERROR”,“HttpRequestId”:“4da1611b-354e-4faf-8e21-5bd5ec893c99”,“HttpRequestNumber”:9,“HttpSessionId”:“94c0f96d-3f71-46df-824d-56a88331940b”} {“@t”:“2025-09-09T10:53:03.6121212Z”,“@mt”:“Starts rebuilding the cache. This can be a long running operation”,“@tr”:“8977f91429d828767db78397502d7e67”,“@sp”:“36f1d82b448b1005”,“SourceContext”:“Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor”,“ActionId”:“7f2bad3e-cfb8-47ce-8250-9edccd883dfc”,“ActionName”:“Umbraco.Cms.Api.Management.Controllers.Upgrade.AuthorizeUpgradeController.Authorize (Umbraco.Cms.Api.Management)”,“RequestId”:“4000007b-0000-fa00-b63f-84710c7967bb”,“RequestPath”:“/umbraco/management/api/v1/upgrade/authorize”,“ProcessId”:19900,“ProcessName”:“iisexpress”,“ThreadId”:37,“ApplicationId”:“0a353b397f57dc2e27e468fd727e71af0c5d5acc”,“MachineName”:“WIN11VM”,“Log4NetLevel”:“INFO “,“HttpRequestId”:“4da1611b-354e-4faf-8e21-5bd5ec893c99”,“HttpRequestNumber”:9,“HttpSessionId”:“94c0f96d-3f71-46df-824d-56a88331940b”} {”@t”:“2025-09-09T10:53:03.7272743Z”,“@mt”:“Database configuration failed”,“@l”:“Error”,“@x”:"System.ArgumentException: LockObject with id=-344 does not exist.\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.SqlServerDistributedLock.ObtainWriteLock()\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.SqlServerDistributedLock..ctor(SqlServerDistributedLockingMechanism parent, Int32 lockId, DistributedLockType lockType, TimeSpan timeout)\r\n at Umbraco.Cms.Persistence.SqlServer.Services.SqlServerDistributedLockingMechanism.WriteLock(Int32 lockId, Nullable1 obtainLockTimeout)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.ObtainWriteLock(Int32 lockId, Nullable1 timeout)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.LockInner(Guid instanceId, Dictionary2& locks, HashSet1& locksSet, Action2 obtainLock, Nullable1 timeout, Int32 lockId)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.EagerWriteLockInner(Guid instanceId, Nullable1 timeout, Int32 lockIds)\r\n at Umbraco.Cms.Core.Scoping.LockingMechanism.WriteLock(Guid instanceId, Nullable1 timeout, Int32 lockIds)\r\n at Umbraco.Cms.Core.Scoping.CoreScope.WriteLock(Int32 lockIds)\r\n at Umbraco.Cms.Core.Services.LongRunningOperationService.RunInner[T](String type, Func2 operation, Boolean allowConcurrentExecution, Boolean runInBackground, CancellationToken cancellationToken)\r\n at Umbraco.Cms.Infrastructure.HybridCache.DatabaseCacheRebuilder.RebuildAsync(Boolean useBackgroundThread)\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor.RebuildCache()\r\n at Umbraco.Cms.Infrastructure.Migrations.MigrationPlanExecutor.ExecutePlanAsync(MigrationPlan plan, String fromState)\r\n at Umbraco.Cms.Infrastructure.Migrations.Upgrade.Upgrader.ExecuteAsync(IMigrationPlanExecutor migrationPlanExecutor, ICoreScopeProvider scopeProvider, IKeyValueService keyValueService)\r\n at Umbraco.Cms.Infrastructure.Migrations.Install.DatabaseBuilder.UpgradeSchemaAndDataAsync(MigrationPlan plan)”,“@tr”:“8977f91429d828767db78397502d7e67”,“@sp”:“36f1d82b448b1005”,“SourceContext”:“Umbraco.Cms.Infrastructure.Migrations.Install.DatabaseBuilder”,“ActionId”:“7f2bad3e-cfb8-47ce-8250-9edccd883dfc”,“ActionName”:“Umbraco.Cms.Api.Management.Controllers.Upgrade.AuthorizeUpgradeController.Authorize (Umbraco.Cms.Api.Management)”,“RequestId”:“4000007b-0000-fa00-b63f-84710c7967bb”,“RequestPath”:“/umbraco/management/api/v1/upgrade/authorize”,“ProcessId”:19900,“ProcessName”:“iisexpress”,“ThreadId”:37,“ApplicationId”:“0a353b397f57dc2e27e468fd727e71af0c5d5acc”,“MachineName”:“WIN11VM”,“Log4NetLevel”:“ERROR”,“HttpRequestId”:“4da1611b-354e-4faf-8e21-5bd5ec893c99”,“HttpRequestNumber”:9,“HttpSessionId”:“94c0f96d-3f71-46df-824d-56a88331940b”}
{“@t”:“2025-09-09T10:53:03.7273646Z”,“@mt”:“Failed {StepName}, with the message: {Message}”,“@l”:“Error”,“@tr”:“8977f91429d828767db78397502d7e67”,“@sp”:“36f1d82b448b1005”,“StepName”:“DatabaseUpgradeStep”,“Message”:“The database failed to upgrade. ERROR: The database configuration failed with the following message: LockObject with id=-344 does not exist.\n Please check log file for additional information (can be found in ‘LoggingSettings.Directory’)”,“SourceContext”:“Umbraco.Cms.Core.Services.Installer.UpgradeService”,“ActionId”:“7f2bad3e-cfb8-47ce-8250-9edccd883dfc”,“ActionName”:“Umbraco.Cms.Api.Management.Controllers.Upgrade.AuthorizeUpgradeController.Authorize (Umbraco.Cms.Api.Management)”,“RequestId”:“4000007b-0000-fa00-b63f-84710c7967bb”,“RequestPath”:“/umbraco/management/api/v1/upgrade/authorize”,“ProcessId”:19900,“ProcessName”:“iisexpress”,“ThreadId”:37,“ApplicationId”:“0a353b397f57dc2e27e468fd727e71af0c5d5acc”,“MachineName”:“WIN11VM”,“Log4NetLevel”:“ERROR”,“HttpRequestId”:“4da1611b-354e-4faf-8e21-5bd5ec893c99”,“HttpRequestNumber”:9,“HttpSessionId”:“94c0f96d-3f71-46df-824d-56a88331940b”}

the hash in the UmbracoKeyValues table in your db indicates it’s umbraco 16.. You’ll need to revert to your v13 db.

Usually you updated to 16, and then downgraded the cms nuget package back to 13.. but your DB doens’t get reverted to v13 at that point, it’s now a v16 DB.

But that’s impossible - i never had v16, and I restored db backup (from prod db) which is v13.10, still says v16. Is that hash in the db, or some file?

It’s in the umbracoKeyValue table in your database.

Note, for the models you can patch it temporarily using this:

I checked my newly restored (from prod) db, its {CC47C751-A81B-489A-A2BC-0240245DB687}, but website is v13.10 (if i login to backend and click on logo). Update fails again. Don’t know how prod db can be v16 when web says its v13, i never ran Update there, and works just fine!
Can i just update that db field with v13.10 GUID?

Looks like that’s the last DB migration for 13 branch.. and actually 13.5

So looks like maybe wrongly reported version…

Looks like it’s just getting the major version of the intended upgrade version? and not the current version.. with a TODO no less. :slight_smile:

  OldVersion = new SemVersion(_umbracoVersion.SemanticVersion.Major), 
  // TODO can we find the old version somehow? e.g. from current state

To be specific the return to scripting hell did not actually answer some of the questions raised by the reasoning given, whilst I applaud using webcomponents, in the version I looked at (v15) forced you down the TS/LIT pathway rather than treating each component as a single enclosed entity which is what webcomponents are supposed to be.

It also forced using the scripting to do what should be backend only tasks such as registering dashboards within the system. This does allow more live changes without having to restart at the expense of flexibility, simplicity (IMO tests are easier when the main logic is all in one language) and speed. Also I doubt this still holds true, but I previously benched the dashboards being added via the JS method taught in the classes (v9) and via the backend using the interfaces and there was an order of magnitude difference in speed.

While there are workaround packages, other methodologies like enabling controllers, or the branch using Blazor by ZauberCMS, the base system is now harder to implement anything without using the proscribed methodology (particularly in reference to having previews of blocks on the page) and is just harder to implement fullstop now we have 2 build processes.

All this change and we still do not have a properly Open/Closed system for databases (at least in v15). (personal grumble that EF will not solve)

Unfortunately this means of the 13 or so people who have master certification in Umbraco in Australia, I now know of 4 who are now looking at other systems to run alongside existing v13 instances of Umbraco. As far as percentages go, that’s not great. Most of the reasoning seems to be the overhead of the 2x build processes. Mine was more that NPM sucks for security and I do not like using scripting for something that is backend only.

In other news, according to the head of web at MS; All of the WebUI is all moving to using Blazor for FE over the next x years. Razor will be replaced by Blazor all of FluentUI will be Blazor native etc.

I hope you’re wrong about Blazor, didn’t hear anything about it (expect they made RazorRuntimeCompilation obsolete, and not investing much in Razor). Maybe they’ll just merge razor/blazor templating engine into one, but we still need server side templating, however its called. Except Blazor folks, I don’t see much traction of web assembly tech, at least not for normal web and SPA, so to me its just yet another Silverlight story.

Why is that, why they don’t update to the latest? Similar issue like mine, broken upgrade/migration?

To the topic; I’ll configure Dashboards, but its just weird to use TS/Lit (to be honest, no clue what this Lit thing even is!) for something that is clearly backend configuration thing, really hope they will rethink that.

Instead of “guys”, may we suggest, for example: “folks", “Umbracians”, “all”, or “everyone”? We use gender inclusive language in this forum :grinning_face: (read more)

razor is almost blazor already anyway, I doubt it’ll end up like silverlilght as the framework is in place and it doesn’t rely on any inbuilt windows libraries like silverlight did (it uses the Os’s inbuilt browser for local stuff, and web it renders to html), so nothing for MS to have to keep up to date. Also silverlight was a POS to begin with, blazor actually works, a couple wierd quirks, but nothing compared to windows forms issues or xaml issues.

WASM has been fully supported in browsers since 2016, but you only use wasm for the blazor client-side stuff, you can also have hybrid and server components (like htmx) which will operate only on the server side, then send the complete html to the client.

For websites it uses SignalR for server-side component comms, for client side it is wasm, so no comms library is necessary. I note SignalR is already in Umbraco 15 for event handling.

What is Lit

A framework, for creating JS web components (web components do not actually need to use JS at all, but the Umbraco ones require it for service/library access)

Lit component example

import {LitElement, css, html} from ‘lit’;
import {customElement, property} from ‘lit/decorators.js’;

@customElement(‘simple-greeting’)
export class SimpleGreeting extends LitElement {
    // Define scoped styles right with your component, in plain CSS
    static styles = css    :host {       color: blue;     }  ;

    // Declare reactive properties
    @property()name?: string = ‘World’;

    // Render the UI as a function of component 
    staterender() { return html<p>Hello, ${this.name}!</p>; }
}

Same example in Blazor, (although you can include the css as a separate file if you need to be able to change it per instance of the component in use and it will keep it localised to that individual instance of it)

// Define scoped styles right with your component, in plain CSS
<style>
    :Host { color:blue; }
</style>
<p>Hello, @name!</p>

@code 
{
    public string name {get; set;} = "World";
}

**
Re: Umbraco and others keeping an eye on alternates**

I was already doing this as soon as I found out about the forced scripting for anything backoffice related because I dislike scripting, and I do not like the extra crap TS adds to the end-result JS file.
One of the others actually told me about the issue with blocks.

The main reason I was given for having other things on the side (although they are not switching yet AFAIK) is because of the additional dev time to setup, and additional time for maintenance/tech debt to have another build process and another package manager (NPM) operating alongside NUGET. If a bug occurs determining what the issue is now requires diving into JS and .NET.

This costs money and makes us less competitive compared to php/js CMS’s which can already be hosted far cheaper than Umbraco due to their more flexible nature in regards to databases and hosting environments.

If they are security conscious it also means having the NPM stuff inside a secured vm (NPM has several major issues with security, including using system authority when installing packages into a project which is a huge problem).

So essentially you are looking at increased overheads and tech debt going forward, thankfully lit seems pretty lightweight, but the fact that for server-only stuff like adding a dashboard we now have to use JS is basically meaning a lot of these guys are seeing extra work for the same output.

To give an example - I made a plugin ages ago that allowed Umbraco forms to integrate with clients SAP, Salesforce, and other ERP/ERM systems, the single plugin did a bunch of them.

The best part was that the clients could update the parameters and multiple endpoints for those systems themselves easily form a config dashboard and the form.

On submission of the form, the relevant data would be: validated, pulled out of the form, converted, and submitted to the appropriate external system’s URL depending on what they had set inside the form and the plugin settings. Then responses logged locally (sometimes we would also be pulling in data regularly too).

None of the above system required any JS, everything ran in backend functionality using .NET libraries, HTML5 + CSS3 for the user-side interfaces. JS was used for some html validation (prior to .net validation) for the dashboard and minor dynamic FE changes.

So I had:

  • NUGET package manager + standard build
  • .Net library service for submission & config of settings
  • .NET Forms extension
  • Composer/component setup for custom local tables
  • .NET MVC controllers for any views (allows for additional or external security checks)
  • .NET IDashboard implementation - registers the dashboard on first start of program provides security settings
  • HTML & CSS for any views, minor JS for any purely dynamic elements.
  • Language file
  • .Net - Tests

Now to do the same in Umbraco 15 when I looked into it, it looks like:

  • NUGET package manager + standard build
  • .Net - library service for submission & config of settings
  • .Net - Forms extension
  • .Net - custom Security (unsure how this will go with the backoffice TS/Lit stuff)
  • .Net - Composer/component setup for custom local tables
  • .Net - Tests
  • NPM Packages + NPM build
  • TS/LIT Dashboard Registration
  • TS/LIT Dashboard Views
  • TS/LIT logic (was part of the controller/razor view previously)
  • HTML + css for views
  • TS - Tests
  • Manifest File
  • language file

So now there is a little bit of extra work there and every time I make any change it may mean 2 builds instead of 1, doubling the amount of time spent in build, but that also means 2 build processes that can break.

There are several big (to me) problems:

  • I had one test project which could test all the other libraries and services logic. Now I have to have 2.
  • If I need to modify this in 6 months, or worse, have to onboard someone. I have to be able to remember 3 different language frameworks, C# .NET, TypeScript (which is very similar as it was MS too), and LIT, in the first instance I only had to know C# .NET.
  • Additionally the main logic of how my package works is split in half, one half in .NET the other in TS/Lit.
  • I have to read a manifest file to see what is happening for some of the code
  • Debugging typescript is not very straight forward. It parses down to JS, but is much harder to read, meaning now you need debugging tools for that.
  • NPM is very environment sensitive, particular settings and other programs changes to environment settings can cause it to fall over, so if you do multiple different types of projects on the one system, best to use a containerised development system or vm.

Now if you want to use TS/Lit, NPM or even angularjs (nothing like having a fe mvc stack on top of a be mvc stack) that is fine, you should be able to as long as it doesn’t compromise the underlying security and stability (unless you mean to do that).

My issue is that we are forced to use the JS based web components setup, and that the interfaces we used to be able to use have been removed, and now they have to hit other js functions which in turn will then access the .NET services to do what we could have done in one step.

There is a plugin that allows you to create a dashboard setup in C# (I think it may generate the JS for you), ZauberCMS allows for blazor, and there is another plugin that reinstates the controller/view pattern to allow razor for Umbraco.

Is the system msg about using ‘guys’ automated? Might want to check that, as the term ‘guys’ has always been used as a gender neutral term to mean a group of people of any sex (typically associated with each other), first popularised in the general public in the movie American Graffitti I think?

The singular is gendered.

Hi @hudo

I just spotted this thread. I back the comment from Lee, but just wanted to add a perspective which may have drowned a bit here, but might be the right fit for you.

Web Components is the new browser standard for bringing encapsulated components, providing a very nice separation of concerns with its ShadowDOM, resolving all sorts of styling problems that occurred in previous versions. As well for DOM manipulations, giving a clear boundary for each component to be the owner of.

As well, they are framework agnostic, meaning how you write these is a free choice of yours.

More importantly, they do not need to be written with TypeScript or compiled by Vite or use any NPM packages.
They could be built with any framework of choice that compiles into Web Components, and I’m pretty sure Blazor is one of them.
If you are going to make a simple Dashboard or even a Property Editor, you might as well stick with plain JS, and we have an article describing just that here:

And this article could have been even simpler without making the Component a UmbElement(using the UmbElementMixin) and utilizing the Context API for consuming the Notification Context — you do not need that.

So just to make the simple example I stripped out some things and here you go:

const template = document.createElement("template");
template.innerHTML = `
  <style>
    :host {
      padding: 20px;
      display: block;
      box-sizing: border-box;
    }
  </style>

  <uui-box>
    <h1>Welcome to my dashboard</h1>
  </uui-box>
`;

export default class MyDashboardElement extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: "open" });
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
}

customElements.define("my-vanilla-extension", MyDashboardElement);

But before you go write a ton of JS Web Components, I may argue why the introduction of TypeScript has been wished upon for a long time.

TypeScript is the frontend solution to bringing Types and not only does this help you prevent a code mistake, but more importantly, it gives you IntelliSense. In previous versions, you worked in the blind, copying from docs or by debugging in the browser. Now, as you type, you can see your opportunities, and there is even JSDocs bringing descriptions and examples right at hand.
In that perspective, we have more documentation than ever because of this.

As Lee mentions, it’s an investment that pays off. Once you get the basics, you have Intellisense at hand to guide you to the top.

———

Additionally, then we can always agree that Documentation and Pre-configured packages can be polished to soften that start, but that is also a process, and we just got started with this project.

Also notice, there is a dotnet new template for initiating a new Package that is quite popular:

Used in this way:
dotnet new umbraco-extension --include-example --site-domain 'https://localhost:44346'

Notice this command gives you an example package that brings custom end-points etc. — A nice way to learn by getting hands on.

And if you want to build a package then this one gives even more and the configuration to easily turn it into a package:

Let me know what you think about this, and thanks in advance :slight_smile:

1 Like

Thank you for this detailed explanation, but i know what web component and TS are (I work daily with React and TS), just wasn’t familiar with Vite. I can add this front end configuration for Dashboard if needed, my question was more about design/architecture decision about need of JS project to register Dashboard, instead of old c# approach. I hoped there’s something for backward compatibility. For my simple usage its a big overkill.

My main issue still remains - updating to latest isn’t possible because Umbraco thinks i am on v16, even though i am on v13, and that TODO in the source code, looks like a bug. Looks like I’ll be stuck on v13.

1 Like

The error is maybe a bit misleading, what it should say is that your database is trying to be upgraded to 16.2.0 (to a migration with guid BE11D4D3-3A1F-4598-90D4-B548BD188C48).

This is because there are v16 dlls in your current project.

When it says “Detected current version 16.0.0”, I think that should be looked at - seems like a bug, it should have detected 16.2.0 - but maybe there’s some kind of logic that I’m forgetting about. I don’t think at this point of the upgrade process Umbraco can know which version you came from, only what version you’re trying to run right now.

Anyway, long story just to say that this is a known bug at the moment and the workaround is listed here: Error upgrading from Umbraco 13 to 16: LockObject with id=-344 does not exist. · Issue #20037 · umbraco/Umbraco-CMS · GitHub

This will be fixed in 16.3.0 which is coming out in a few weeks, but the workaround should help make your upgrade succeed.

1 Like

Great to hear! Thanks for quick response!