If you’ve exhausted all other options, you may need to resort to template overrides. This technique allows you to override the entire template of any Ember Component or Route from your theme/plugin.
This is not a recommended way of customizing Discourse. Day-to-day changes in Discourse core will conflict with your template override eventually, potentially causing catastrophic errors when rendering the forum.
If you decide to take this approach, make sure you have sufficient automated testing and QA processes to detect regressions. If you distribute a theme/plugin with template overrides, please ensure forum admins are aware of the stability risks your theme/plugin carries.
To override an Ember Component template (i.e. anything under
components/* in Discourse core), you should create an identically-named
.hbs in your theme/plugin. For example, to override the template for the
badge-button component in Discourse core, you would create a template file in your theme/plugin at this location:
The override must always be nested inside the
/templates directory, even if the core component has a ‘colocated’ template.
Overriding route templates (i.e. all the non-component templates under
templates/*) works in the same way as components. Create an identically named template in your theme/plugin. For example, to override
discovery.hbs in core, you would create a file like
Discourse’s “raw” template system will soon be replaced by regular Ember components. But in the meantime, overriding raw templates works in the same way as Ember templates. For example, to override
topic-list-item.hbr in core, you could create a file like:
If multiple installed themes/plugins override the same template, the ‘winner’ is the one with the lowest-numbered ranking in this list:
- Theme overrides (highest theme ‘id’ wins)
- Plugin overrides (latest alphabetical plugin name wins)
This precedence also means that you can override plugin templates from themes. Technically you can also override theme templates from other themes, and plugin templates from other plugins, but the behaviour can be surprising because of the dependence on plugin-name and theme-id.
Discourse assembles and prioritises templates in the DiscourseTemplateMap class. For colocated component templates, that information is used during app initialization to replace the core template associations. For all other templates, the map is used by the resolver at runtime to fetch the correct template.