sidebarMod: Add/Remove Sidebar Links and Sections

AI-generated summary

shyguy introduced sidebarMod, a JavaScript script for dynamically adding or removing sidebar links and sections in Discourse using MutationObserver and promises. It supports positioning links (prepend, append, before/after), removing sections or links (including the ⋮More button), and conditionally applying changes based on user type (guest vs. registered). The script is designed to complement Discourse’s built-in custom sidebar sections feature and is installed via a theme component’s Head section. Configuration is handled via injections and removals arrays, with examples provided for clarity. shyguy later updated the script to support data-link-name. literarymachine found the script helpful for dynamically updating sidebar sections during page transitions but noted that clicking custom links triggered full page refreshes. They later found a solution to prevent this behavior, referencing a meta thread on reloading page body without full refresh. The author also inquired about implementing such functionality “the right way” via Discourse’s plugin API or Ruby, suggesting current DOM manipulation is a workaround due to API limitations.

sidebarMod

here’s my script for modding the sidebar (first mentioned in the custom sidebar sections topic).

it uses promises and MutationObserver to watch the sidebar for changes (e.g. from expanding or collapsing) and add/remove stuff in a performant way.

i think i made it flexible enough for most use cases. you can add links (positioned by appending, prepending, or inserting before/after existing links), remove sections, remove links, and even remove ⋮More.

it’s even possible to change the behavior if the viewer is a guest or a registered user. for example, i’m using it to remove a custom section that is irrelevant to guests.

it’s a nice complement to the new custom sidebar sections feature (enabled via SiteSetting.enable_custom_sidebar_sections), so i didn’t bother adding a feature to create sections.

let me know if you find bugs or need extra features.

installation

create a new theme component and paste it into Head. remember to enable it for your theme.

configuration

you only need to edit injections and removals near the top.

i suggest just leaving it as-is at first so you see what it’s doing. i tried to make the example config illustrative.

i’m personally using it like this:

  /**
   * link positioners:
   *   (bool) prepend, append: prepend/append link to section
   *   (str)  addBeforeKebab, addAfterKebab: add link before/after existing link
   * link visibility:
   *   (str)  injectFor: inject link only for 'anon' users, only for 'registered' users, or for 'both' (default: 'both')
   */
  injections: [
    { sectionSelector: '.sidebar-section[data-section-name="community"]',
      links: [
        { text: 'Guidelines', kebab: 'guidelines', title: 'Guidelines for using this site', href: '/guidelines', icon: 'gavel', addBeforeKebab: 'faq', injectFor: 'registered' }
      ]
    },
    { sectionSelector: '.sidebar-section[data-section-name="categories"]',
      links: [
        { text: 'Site Map', kebab: 'site-map', title: 'Site Map', href: '/t/32', icon: 'map-marker-alt', prepend: true }
      ]
    }
  ],

  /**
   * section options:
   *   (str) removeFor: remove section only for 'anon' users, only for 'registered' users, or for 'both' (default: 'none')
   *   (str) removeMore: remove '⋮More' only for 'anon' users, only for 'registered' users, or for 'both' (default: 'none')
   *                       useful if you know it's empty due to link removals
   * link removal options:
   *   (str) removeFor: remove link only for 'anon' users, only for 'registered' users, or for 'both' (default: 'both')
   */
  removals: [
    { sectionSelector: '.sidebar-section[data-section-name="community"]',
      links: [{ kebab: 'badges', removeFor: 'anon' }]
    },
    { sectionSelector: '.sidebar-custom-sections .sidebar-section[data-section-name="my-topics"]',
      removeFor: 'anon'
    }
  ],

questions from me

i investigated doing this with the API, but i don’t think enough stuff is implemented.

if i wanted to do this “the right way” instead of hacking things into the DOM, how would i do that? would i need to make a plugin with ruby? any hints would be appreciated.

updated to work with data-link-name

https://github.com/discourse/discourse/commit/2eb60c9713ed15b81718f896811c0b4da4aee003

Thanks, this was really helpful for me implementing a custom sidebar section that needs to be updated on page transitions (see Making custom changes to the sidebar programmatically). One problem I have is that when the custom links are clicked, a full page refresh is triggered. Did you somehow get around this?

FYI, found a solution here: Reload page body when clicking a link in a custom header