Inline script tags moderniseren voor templates en JS API

Using <script type='text/discourse-plugin> or <script type='text/x-handlebars'> in themes is now deprecated. Any use of these tags in themes should be updated according to the instructions below.

Regular <script> and <script type='text/javascript'> are unaffected by this change.

Timeline

These are rough estimates, subject to change

  • May 2025 - console deprecation messages enabled

  • July 2025 - admin warning banners enabled

  • Late September 2025 - removal of feature

Converting <script type='text/x-handlebars'>

Templates introduced using this method should be moved to dedicated .hbs files, or refactored into gjs files.

To keep as HBS, connector templates can be placed in:

{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs

and component templates can be placed in:

{theme}/javascripts/discourse/components/{component-name}.hbs

To build connectors and components in the modern .gjs format, check out this chapter of the theme developer tutorial:

Converting <script type='text/discourse-plugin'>

Code inside these tags can be migrated to a dedicated JavaScript file.

If you develop your theme via the admin panel interface, copy the code out of the <script>, and move it into the JS tab (where it says // your code here).

If you develop your theme locally, create a new file at

{theme}/javascripts/discourse/api-initializers/init-theme.js

then add this wrapper, and place your code in the indicated spot:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  // Your code here
});

In script tags, the only way to import other JS modules was using the require() syntax. While that will still work in a .js file, it will soon be deprecated, so now would be a good time to convert it to modern ES6 imports. For example:

- const I18n = require("discourse-i18n").default;
+ import I18n from "discourse-i18n";
- const { h } = require("virtual-dom");
+ import { h } from "virtual-dom";

For more information on JS initializers:

19 likes

Maybe a very dumb question, but I have a very very simple theme component that I put directly into the admin console under <head>:

<script type="text/x-handlebars" data-template-name="/connectors/top-notices/whos-online-below-site-header">
{{whos-online}}
</script>

If I’m following this post correctly, does it mean that I now have to create a separate theme component folder, host it on GitHub and add the component just for something as simple as adding to a plugin outlet?

I sure hope not, as it’ll break most of my simple theme components :grimacing:

Er is nu het JS-tabblad, dus je kunt waarschijnlijk api.renderInOutlet nu gebruiken.

1 like

Ah, I didn’t see that this was possible to do with connectors/components as well, but in the linked article found this:

Maybe easier than I thought, thank you!

2 likes

Thank you for this post!
May be a very basic question I believe:
Since we do not have a sandbox, I need to be sure before I proceed.
I have to update a theme affected so am I correct if say that all the code related to ā€œScriptā€ from ā€œheadā€ tab need to be moved into the JS tab as illustrated below:

Almost, but not quite. You’d want to remove the script tags, and change the imports to something like:

import { ajax } from "discourse/lib/ajax";

Then, paste all this in the JS tab, inside:

Our Discourse site (hosted by Discourse) is currently generating the following error bar (which is what led me to this thread):

I’m not aware that we’ve done any cutomization of the ā€˜Light’ theme of our own, and looking at its admin page, am not seeing anything suggesting this is anything more than the system-provided default (but could easily be missing something).

For a hosted site like ours, is this likely to self-resolve over time, or does it require some action on our part?

Thanks,
-Brad

You will need to take action to resolve this - it won’t go away on its own.

I took a quick look at your site in chrome dev tools, and it looks like the relevent code is related to adding the ā€˜chapel’ language to highlightjs.

If you visit your ā€˜Light’ theme, and hit ā€˜edit code’, you should be able to find this under one of the HTML tabs. Then you can follow the instructions in the OP of this topic to move it to the ā€˜JS’ tab.

1 like

Bedankt @david! Ik was vergeten dat we enkele aanpassingen hadden gedaan om Chapel-syntaxisaccentuering te krijgen en ik weet niet zeker of ik er zelf was gekomen op basis van het foutbericht, dus ik waardeer de hulp en de aanwijzingen.
-Brad

1 like

Ik heb een eenvoudig .html-bestand:

<script type='text/x-handlebars' data-template-name='/connectors/below-site-header/oprs-top-container'>
    <div id='WW_T_D_1' class='oprs-top-leaderboard'></div>
</script>

Ik ben nogal verward door de verschillende manieren om deze migratie uit te voeren. Ik zou het waarderen als iemand uitlegt wat te doen. Bedankt.

Alleen renderInOutlet naar de connector

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  api.renderInOutlet("below-site-header", 
    <div>
      <div id='WW_T_D_1' class='oprs-top-leaderboard'></div>
    </div>);
});
2 likes

Thank you. I tried and it didn’t work :confused:

This my structure and these are

below-site-header.js


export function test() {
    let test2 = document.querySelector('.test');
    console.log('test ', test2);
}

And below-siteheader-connectors.hbs

<div class="test"></div>

I’m new to this so any help is appreciated. I took this repo from a previous dev.

Hallo, kun je de link naar je Github-repo delen? Bedankt!

Dus ik heb mijn kleine ā€œmaak-avatar-groterā€ script in het JS-tabblad geplakt (uit Desktop - <head>), en dat werkt vrij eenvoudig, maar is er tenminste een snelle 'n vuile manier om het alleen toe te passen op Desktop? Mijn mobiele avatars zijn ook nu groot en het ziet er allemaal nogal gek uit.

De code voor de referentie is:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  api.changeWidgetSetting('post-avatar', 'size', '70');
});

Hmm… misschien dit aanpassen met CSS?

Of, misschien:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  const site = api.container.lookup("service:site");
  if (!site.mobileView) {
    api.changeWidgetSetting('post-avatar', 'size', '70');
  }
});

Iets uit het blote hoofd.

3 likes

Dat heeft perfect geholpen, dank je wel!

1 like

Just a friendly reminder: changeWidgetSetting on post-avatar is a deprecated API and will be removed soon.

Maybe you should change your code to this

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  const site = api.container.lookup("service:site");
  if (!site.mobileView) {
    api.modifyClass("component:post/avatar", (SuperClass) => class extends SuperClass {
      get size() { return "70"; } 
    });
  }
});
5 likes

I think there’s also an official theme component for this as well? Avatar Size and Shape

Not sure if it fits the particular use case, but it seems like it should (with the added bonus that someone will fix it if it needs updating :slight_smile:)

7 likes

Ik ben helemaal opgewaardeerd van quick 'n dirty naar officieel ondersteund, bedankt allemaal!

4 likes

Noting for people with legacy components (using separate Desktop/Mobile handling) that the JS tab is only available in the Common section - hopefully saves somebody else a few searches :slight_smile:

1 like