# Developing Discourse Themes & Theme Components

**URL:** https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648
**Category:** Developer Guides
**Tags:** reference, tutorial, theme-guides
**Created:** [August 1, 2018, 12:00pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648 "2018-08-01T12:00:39Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [August 1, 2018, 12:00pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/1 "2018-08-01T12:00:40Z")

</div>

Discourse Themes and Theme Components can be used to customize the look, feel and functionality of Discourse’s frontend. This section of the developer guides aims to provide all the reference materials you need to develop simple themes for a single site, right up to complex open-source theme components.

This introduction aims to provide a map of all the tools and APIs for theme development. If you prefer a step-by-step tutorial for theme development, jump straight to:

> [@Theme Developer Tutorial: 1. Introduction](https://meta.discourse.org/t/theme-developer-tutorial-1-introduction/357796):
>
> This tutorial will teach you how to create a Discourse Theme or Theme Component from the ground up. While this topic assumes no previous experience working on Discourse themes, it does assume some prior experience using [HTML](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML), [CSS](https://developer.mozilla.org/en-US/docs/Learn/CSS) and [JavaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript). It’ll also help if you [know your way around GitHub](https://guides.github.com/activities/hello-world/). What are Discourse themes? A theme or theme component is a set of files packaged together designed to either modify Discourse visually or to add new features. Themes In general, themes are not suppo…

## Themes vs. Theme Components

**Discourse Themes** can be used to customize the frontend user experience using CSS and JavaScript. Each theme has its own git repository, and community admins can generally install and manage them via the Discourse admin panel, even on shared hosting platforms.

**Theme Components** are themes which are intended for use alongside other Theme Components, as part of an overall Theme. From a development point of view, Theme Components and Themes are almost identical. In these guides, the phrase “Theme” and “Theme Component” are used interchangeably.

## Prerequisites

Firstly, make sure you understand [how to use existing themes and theme components](https://meta.discourse.org/t/beginners-guide-to-using-discourse-themes/91966) in Discourse. Using ready-made themes is the quickest and safest way to customize your community. If you need more, then it’s time to consider writing your own theme.

As part of [Discourse’s overall architecture](https://meta.discourse.org/t/349939), Discourse Themes are built using standard HTML, CSS, JavaScript technologies, and make use of Ember concepts for more advanced UIs. These reference guides assume a base-level understanding of these technologies, and link out to external references where possible.

Discourse is a fast-moving project, and as such any custom theme will [require maintenance over time](https://meta.discourse.org/t/261388). Make sure you consider this as part of your planning & development processes.

## Getting Started

- [Theme CLI](https://meta.discourse.org/t/install-the-discourse-theme-cli-console-app-to-help-you-build-themes/82950)
- [Theme Creator](https://meta.discourse.org/t/get-started-with-theme-creator-and-the-theme-cli/108444)
- [File structure of theme](https://meta.discourse.org/t/structure-of-themes-and-theme-components/60848)

## Frontend Customization

- [Color Schemes](https://meta.discourse.org/t/61196)
- [JavaScript API](https://meta.discourse.org/t/41281)
- [Outlets](https://meta.discourse.org/t/32727)
- [Transformers](https://meta.discourse.org/t/349954)
- [modifyClass](https://meta.discourse.org/t/262064)

## More!

Check out the rest of the [Developer Guides](https://meta.discourse.org/c/documentation/developer-guides/56) !

* * *

This document is version controlled - suggest changes [on github](https://github.com/discourse/discourse/blob/main/docs/developer-guides/docs/05-themes-components/01-developing-themes.md).

---

<div class="post-metadata">

### Author: ![rsigg](https://avatars.discourse-cdn.com/v4/letter/r/ac8455/32.png) [@rsigg](https://meta.discourse.org/u/rsigg)
#### Post date: [June 21, 2024, 9:02pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/136 "2024-06-21T21:02:47Z")

</div>

A lot of old and/or dead links and references in the [The PluginApi - modifyClass() section](https://meta.discourse.org/t/beginners-guide-to-developing-discourse-themes/93648?silent=true#modifyclass-29) section…

> [@Discourse](#):
>
> [https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/controllers/composer.js#L578](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/controllers/composer.js#L578)

This file has changed so much that `checkReplyLength` doesn’t even exist any more…

And later in the same section:

> [@Discourse](#):
>
> [https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/components/discovery-categories.js](https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/components/discovery-categories.js)

This link just results in a “404 - Page not found” error…

I gave up using these docs after that…

---

<div class="post-metadata">

### Author: ![JammyDodger](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jammydodger/32/254611_2.png) [@JammyDodger](https://meta.discourse.org/u/JammyDodger)
#### Post date: [July 26, 2024, 6:13pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/137 "2024-07-26T18:13:35Z")

</div>

A post was split to a new topic: [User card template or widget?](https://meta.discourse.org/t/user-card-template-or-widget/318657)

---

<div class="post-metadata">

### Author: ![Overgrow](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/overgrow/32/478189_2.png) [@Overgrow](https://meta.discourse.org/u/Overgrow)
#### Post date: [August 12, 2024, 10:48am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/138 "2024-08-12T10:48:00Z")

</div>

> [@Discourse](#):
>
> If you want to fire scripts when a component is loaded you can use something like this

Docs seem a bit outdated in this part.. (also `api.modifyClass` complains about pluginId missing). How can I run a script when `about-page` is loaded? This one doesn’t seem to work (no errors though). I had mixed results with some other components. Thanks.

```js
<script type="text/discourse-plugin" version="0.11.1">

api.modifyClass("component:about-page", {
  pluginId: 'discourse-about-theme',

  didInsertElement() {
    this._super(...arguments);
    console.log("Welcome to the about page!");
  }

});

</script>

```

---

<div class="post-metadata">

### Author: ![Don](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/don/32/228726_2.png) [@Don](https://meta.discourse.org/u/Don)
#### Post date: [August 12, 2024, 11:17am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/139 "2024-08-12T11:17:07Z")

</div>

Hello 👋[about-page](https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/components/about-page.gjs) is now in `.gjs` which also means it’s not modifiable anymore that way. If you want to make changes you have to use one of the connectors available on that page.

You can check these easily with [Plugin outlet locations theme component](https://meta.discourse.org/t/plugin-outlet-locations-theme-component/100673) or check in the file `<PluginOutlet>`.

---

<div class="post-metadata">

### Author: ![Overgrow](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/overgrow/32/478189_2.png) [@Overgrow](https://meta.discourse.org/u/Overgrow)
#### Post date: [August 12, 2024, 2:22pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/142 "2024-08-12T14:22:04Z")

</div>

Thank you very much. Makes sense. I have used a connector instead, works fine.

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [February 5, 2025, 11:03am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/143 "2025-02-05T11:03:38Z")

</div>

Is this guide even accurate anymore? I read thru the whole thing to try to create a theme component and then looked at the sample theme components and none of them use the instructions that they are supposed to. For example, in looking at discourse-brand-header theme component it seems to have been refactored from using stuff like api.createwidget in the header.html to using a totally different code with initializers, Components etc. Extremely complex code. The guide talks about using the API method with widgets, but that’s not what any of the components use at all. Is there an updated guide or something to use Components?

Edit: Supposedly widgets API is going away, but are there any guides on what to use instead? The entire guide here seems to be based on code that is deprecated?

---

<div class="post-metadata">

### Author: ![NateDhaliwal](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/natedhaliwal/32/313494_2.png) [@NateDhaliwal](https://meta.discourse.org/u/NateDhaliwal)
#### Post date: [February 5, 2025, 11:08am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/144 "2025-02-05T11:08:22Z")

</div>

That’s true. The guide ought to be updated. However, some parts are still quite relevant, like the structure of files, etc.

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [February 5, 2025, 11:12am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/145 "2025-02-05T11:12:26Z")

</div>

Yeah, it seems like SCSS is relevant, but otherwise, it seems like all sample theme components use Components and have been refactored to an entirely different codebase than what is taught here. I went thru all the components they link to in the Plugin API section and every single one has been refactored in a manner that is totally different than what is taught here in the guide. Widgets are not used anymore at all. It’s all Components. Is there a guide on how to actually properly use the new Components as Widgets are going away?

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [February 5, 2025, 11:17am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/146 "2025-02-05T11:17:15Z")

</div>

So I came across this post for example, just now: [Upcoming Header Changes - Preparing Themes and Plugins](https://meta.discourse.org/t/upcoming-header-changes-preparing-themes-and-plugins/296544) - so they refactored everything from legacy widgets to Glimmer components? But, this tutorial is all legacy widgets. What are Glimmer components exactly and are there any guides? I feel lucky I caught this early on, before I started developing with legacy widgets. Maybe add a note in this guide that widgets are legacy and shouldn’t be used anymore?

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [February 5, 2025, 11:35am UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/147 "2025-02-05T11:35:09Z")

</div>

Ok, I see Glimmer is new Ember components. But, I took a look at the Discourse TOC code and oh my…what previously had like 10 lines of code now is like 100’s of lines across many files with complex classes, decorators etc. I’m guessing Ember had a React moment and decided that let’s makes things really complicated again. Seems like Theme components are now no longer easy, with a simple widget api, but require extensive coding…

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [February 5, 2025, 12:29pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/148 "2025-02-05T12:29:56Z")

</div>

@ddsgad yes you’re right, most of this guide is extremely out-of-date. I’ve been working on general docs improvements recently, and hope to get this one updates/replaced in the next few weeks.

As you’ve mentioned, real-world examples like DiscoTOC can be a good reference. And then here are some specific guides which are more up-to-date:

- [Install the Discourse Theme CLI console app to help you build themes](https://meta.discourse.org/t/-/82950?silent=true)

- [Using Plugin Outlet Connectors from a Theme or Plugin](https://meta.discourse.org/t/-/32727?silent=true)

- [Customizing the topic list](https://meta.discourse.org/t/-/350411?silent=true)

- [Introducing Discourse developer toolbar](https://meta.discourse.org/t/introducing-discourse-developer-toolbar/346215)

For general information about Ember and its components, I recommend looking at [the Ember guides](https://guides.emberjs.com/release/components/).

---

<div class="post-metadata">

### Author: ![ddsgad](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ddsgad/32/486614_2.png) [@ddsgad](https://meta.discourse.org/u/ddsgad)
#### Post date: [February 5, 2025, 2:45pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/149 "2025-02-05T14:45:10Z")

</div>

Thanks for those links. Very helpful. Currently, we basically just customize stuff in a discourse topic (first post) to make some better designs, so we’ve been able to basically do everything with plain Vanilla javascript (querySelectorAll etc.) and SCSS, so I guess we will just keep to that for now.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [March 18, 2025, 4:11pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/150 "2025-03-18T16:11:00Z")

</div>

The long and out-of-date tutorial in the OP has now been replaced with some more general introduction/signpost information, including a link to a brand new [7-step tutorial](https://meta.discourse.org/t/-/357796) which follows much more modern theme development patterns.

---

<div class="post-metadata">

### Author: ![Arkshine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/arkshine/32/298682_2.png) [@Arkshine](https://meta.discourse.org/u/Arkshine)
#### Post date: [March 18, 2025, 4:32pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/151 "2025-03-18T16:32:32Z")

</div>

I’ve read everything, I enjoyed it! Well explained, and very good introduction!

---

<div class="post-metadata">

### Author: ![NateDhaliwal](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/natedhaliwal/32/313494_2.png) [@NateDhaliwal](https://meta.discourse.org/u/NateDhaliwal)
#### Post date: [March 18, 2025, 11:33pm UTC](https://meta.discourse.org/t/developing-discourse-themes-theme-components/93648/152 "2025-03-18T23:33:05Z")

</div>

I love these guides! Finally deciphered `api.decorateCookedElement`, thanks for the helpful docs once again!
