alkah3st  
                
                  
                    May 19, 2025,  6:00am
                   
                  1 
               
             
            
              I’ve seen a few posts about this but none have definitive answers.
Does the Unreal Engine Discourse (featured on the Discourse “Discover” page) have a completely custom theme, or are there components that can achieve this?
I also notice they display the subcategories as top level links when you click into one, and then beneath it lists all the topics. It looks like what’s happening here is setting “Subcategory List Style” to “Rows” on the parent category to achieve that?
             
            
              1 Like 
            
                
            
           
          
            
              
                alkah3st  
              
                  
                    May 19, 2025,  6:17am
                   
                  3 
               
             
            
              It looks like this may not be something solvable with a component.
However I was able to generate JS and CSS that achieves this with a little AI help, if anyone is interested I am happy to share.
             
            
              3 Likes 
            
            
           
          
            
              
                nathank  
              
                  
                    May 19, 2025, 10:22am
                   
                  4 
               
             
            
              You’ve seen this I take it:
  
  
    What is the name of Unreal Engine’s community theme? Or how can i make a theme like that? 
Unreal Engine Forum 
   
 
And this:
  
  
    This is a heavily customised forum. Something like this will use plugins as well as theme modifications. 
This is something that our partners  can help you with; Discourse can help too of course, if you are on the Enterprise plans  
 
By all means, do share your code. Of course, the challenge with things like this is the ongoing maintenance.
             
            
              2 Likes 
            
            
           
          
            
              
                alkah3st  
              
                  
                    May 19, 2025,  3:57pm
                   
                  5 
               
             
            
              Yeah, it seems a lot of what they’re doing is custom stuff.
My script looks like this:
import { apiInitializer } from "discourse/lib/api";
import { ajax } from "discourse/lib/ajax";
export default apiInitializer("0.11.1", (api) => {
  ajax("/site.json").then((data) => {
    const categories = data.categories;
    // Build map of parent_id => [child_category_ids]
    const childMap = {};
    categories.forEach((cat) => {
      if (cat.parent_category_id) {
        if (!childMap[cat.parent_category_id]) {
          childMap[cat.parent_category_id] = [];
        }
        childMap[cat.parent_category_id].push(cat.id);
      }
    });
    const collapseState = {}; // Tracks collapse state per parent
    function applyCollapseState(parentId, childIds, collapsed) {
      childIds.forEach((childId) => {
        const childEl = document.querySelector(
          `.sidebar-section-link-wrapper[data-category-id="${childId}"]`
        );
        if (childEl) {
          childEl.classList.toggle("is-collapsed", collapsed);
          childEl.classList.add("is-subcategory");
        }
      });
    }
    function ensureToggleExists(parentId, childIds) {
      const parentEl = document.querySelector(
        `.sidebar-section-link-wrapper[data-category-id="${parentId}"]`
      );
      if (!parentEl || parentEl.classList.contains("has-toggle")) return;
      const toggle = document.createElement("span");
      toggle.innerText = collapseState[parentId] ? "▸" : "▾";
      toggle.className = "toggle-subcategories";
      toggle.style.cursor = "pointer";
      toggle.style.marginLeft = "0.5em";
      toggle.onclick = () => {
        const isNowCollapsed = !collapseState[parentId];
        applyCollapseState(parentId, childIds, isNowCollapsed);
        toggle.innerText = isNowCollapsed ? "▸" : "▾";
        collapseState[parentId] = isNowCollapsed;
      };
      parentEl.classList.add("has-toggle");
      const link = parentEl.querySelector(".sidebar-section-link");
      if (link) link.appendChild(toggle);
    }
    api.onPageChange(() => {
      Object.entries(childMap).forEach(([parentId, childIds]) => {
        // Set default collapse state
        if (collapseState[parentId] === undefined) {
          collapseState[parentId] = true;
        }
        applyCollapseState(parentId, childIds, collapseState[parentId]);
        ensureToggleExists(parentId, childIds);
      });
      const container = document.querySelector('[data-section-name="categories"]');
      if (!container) return;
      const observer = new MutationObserver(() => {
        Object.entries(childMap).forEach(([parentId, childIds]) => {
          applyCollapseState(parentId, childIds, collapseState[parentId]);
          ensureToggleExists(parentId, childIds); // <-- Restore toggles
        });
      });
      observer.observe(container, {
        childList: true,
        subtree: true,
      });
    });
  });
});
I just dropped that into the theme’s JS panel. The relevant CSS:
.sidebar-section-link-wrapper.is-collapsed {
  display: none !important;
}
.sidebar-section-link-wrapper.is-subcategory {
  padding-left: 1.5em;
}
.toggle-subcategories {
    float: right;
    display: flex;
    width: 30px;
    align-items: center;
    font-size: .9em;
    line-height: 1;
    height: 30px;
}
It works well enough for my purposes but I wouldn’t recommend this if you have lots of subcategories.