Theme Developer Quick Reference Guide

As themes grow more powerful, there’s more to remember about how they work. We have loads of detailed documentation under #howto / #themes, but if you just need something to jog your memory, this guide may help.

General Resources

:scroll: Beginner’s guide

:scroll: Designer’s guide

:scroll: Developer’s guide

:paintbrush: Theme Creator

:desktop_computer: Theme CLI

:notebook_with_decorative_cover: Theme Directory

:jigsaw: Component Directory

:wrench: Theme Modifiers

File/Folder Structure read more

about.json
settings.yml
common/, desktop/, mobile/
  {common|desktop|mobile}.scss
  head_tag.html
  header.html
  after_header.html
  body_tag.html
  footer.html
  embedded.scss (common only)
locales/
  en.yml
  ...
assets/
  (arbitrarily named files, referenced in about.json)
stylesheets/
  (arbitrarily named files, can be imported from each other, and common/desktop/mobile.scss)
javascripts/
  (arbitrarily named files. Supports .js.es6 .hbs and .raw.hbs)

about.json structure info, available metadata

{
  "name": "My Theme",
  "component": false,
  "license_url": null,
  "about_url": null,
  "authors": null,
  "theme_version": null,
  "minimum_discourse_version": null, 
  "maximum_discourse_version": null,
  "assets": {
    "variable-name": "assets/my-asset.jpg"
  },
  "color_schemes": {
    "My Colour Scheme": {
      "primary": "222222",
    }
  }
}

SCSS

:link: Available CSS Variables

Javascript read more

<!-- Define in </head> section of theme-->
<script type="text/discourse-plugin" version="0.8">
    console.log("I am ", api.getCurrentUser().username);
</script>

:link: JS Plugin API

:link: Multi-file Javascript

Templates read more

<!-- Define in </head> section of theme-->

<!-- Plugin Outlet -->
<script type="text/x-handlebars" data-template-name="/connectors/below-footer/arbitrary-unique-name">
   This is displayed below the footer
</script>

<!-- Override Core -->
<script type="text/x-handlebars" data-template-name="list/topic-list-item.raw">
   This used to be a topic list item
</script>

:link: Locate outlets

Settings read more

settings.yml:

fruit:
  default: apples|oranges
  type: list
  description: # Old method. It's better to define these in the locale files (see below)
    en: English Description
    fr: Description Française

Access from JavaScript:

console.log(settings.fruit);

Access from templates:

{{theme-setting "fruit"}}

Access from scss:

html {
  font-size: #{$global-font-size}px;
  background: $site-background;
}

Translations read more

locales/en.yml

en: 
  my_translation_key: "I love themes"
  theme_metadata: # These are used in the admin panel. They are not made available to your js/hbs files
    description: This theme lets you do amazing things on your Discourse
    settings:
      fruit: A description of the whitelisted_fruits setting

Access from JavaScript:

I18n.t(themePrefix("my_translation_key"))

Access from templates:

{{theme-i18n "my_translation_key"}}
{{d-button label=(theme-prefix "my_translation_key")}}

This document is version controlled - suggest changes on github.

Last edited by @JammyDodger 2024-05-26T09:02:18Z

Check documentPerform check on document:
40 Likes

This is super useful.

Could I also suggest that a useful reference to add is the list of available color transformations:
https://github.com/discourse/discourse/blob/master/app/assets/stylesheets/common/foundation/color_transformations.scss

3 Likes

I must be missing something here, I’m trying to use I18n.t(themePrefix("my_translation_key")) but the Firefox console reports that themePrefix is undefined.
How can I invoke that function from an api function?

The link seems no longer valid.

2 Likes

You’re right. It should be now:

2 Likes

Thanks @th21 and @Arkshine - I’ve updated the link

2 Likes

The Plugin API link changed again:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.gjs

2 Likes

Thanks! Updated :writing_hand:

3 Likes