How to customise the header with a plugin?

I’m trying to make a plugin which will change header into something like this

It doesn’t really matter how does it look, that matters is I don’t want to use customisation on /admin/customize/css_html path. I want to make a plugin which will magically change everything I need.

That I found so far is, there is no template for the header, it renders via virtual-dom.

The way it renders is following:

  1. assets/javascripts/discourse/templates/application.hbs template, which can be overloaded, renders site-header component.

    {{plugin-outlet “above-site-header”}}
    {{site-header canSignUp=canSignUp
    showCreateAccount=“showCreateAccount”
    showLogin=“showLogin”
    showKeyboard=“showKeyboardShortcutsHelp”
    toggleMobileView=“toggleMobileView”
    toggleAnonymous=“toggleAnonymous”
    logout=“logout”}}
    {{plugin-outlet “below-site-header”}}

  2. assets/javascripts/discourse/components/site-header.js.es6 component extends and returns header widget.

    const SiteHeaderComponent = MountWidget.extend(Docking, {
    widget: ‘header’,

    });

    export default SiteHeaderComponent;

  3. assets/javascripts/discourse/widgets/header.js.es6 widget generates virtual-dom for the header.

    export default createWidget(‘header’, {
    tagName: ‘header.d-header.clearfix’,

    html(attrs, state) {}
    });

My thoughts

I can create my own widget my-header which will extend existing header, there I’ll just update html. I don’t want to copy-paste anything into it, I want just to override html() method.

/plugins/discourse-foo/assets/javascripts/discourse/widgets/my-header.js.es6

Then I can create my own my-site-header component which will extend existing site-header with just overriding it to point into my-header widget.

/plugins/discourse-foo/assets/javascripts/discourse/components/my-site-header.js.es6

Then I override application template to show my-site-header component instead of site-header

/plugins/discourse-foo/assets/javascripts/discourse/templates/application.hbs

{{plugin-outlet "above-site-header"}}
{{my-site-header canSignUp=canSignUp
              showCreateAccount="showCreateAccount"
              showLogin="showLogin"
              showKeyboard="showKeyboardShortcutsHelp"
              toggleMobileView="toggleMobileView"
              toggleAnonymous="toggleAnonymous"
              logout="logout"}}
{{plugin-outlet "below-site-header"}}

The question is, how can I extend all of these components and widgets? Can you please point me to the right way of doing that? Thanks.

Based on the screenshot, this seems like something that is plausible to do with just CSS customizations. That would also be much simpler than writing a plugin and would not require updating with new versions of Discourse code.

Well, I knew you going to say that, that’s why I mentioned that I need a plugin :slight_smile:

First of all, because I want to learn how to do plugins, I’ll have to do whole lot more complicated things later. That menu is just an example.

Secondly, I really need that menu to be a plugin, because:

  1. We may reuse it on different projects;
  2. We need a version control, to roll back sometimes;
  3. Some links will be generated from external json;
  4. I want a clean solution. I believe doing it with a plugin is a clean solution;
3 Likes

Sitepoint use a plugin to override the header.
Take a look here:

Thank you for your link, it will be definitely interesting to see how other people are doing it.

As I see now, they are not extending existing header widget. They just copy-pasted it from the core and customised it.
In that case they have to support that code themselves, and Discourse most likely to break it on next update.