# Theme modifiers: A brief introduction

**URL:** https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605
**Category:** Developer Guides
**Tags:** theme-guides
**Created:** [May 6, 2020, 2:35pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605 "2020-05-06T14:35:41Z")
**Posts on this page:** 20
**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: [May 6, 2020, 2:35pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/1 "2020-05-06T14:35:41Z")

</div>

As themes become more ambitious, we’ve been looking for ways to allow them to manipulate core **server-side** behavior. While they will never be given the same level as control as plugins, we can provide some predefined hooks for themes to manipulate.

Introducing: theme modifiers :partying_face:

They are specified using the `modifiers` key in your theme’s `about.json` file.

For a 100% up-to-date list of modifiers, check the database schema at the bottom of [`theme_modifier_set.rb`](https://github.com/discourse/discourse/blob/main/app/models/theme_modifier_set.rb), but here’s a quick summary of what we have so far:

- `serialize_topic_excerpts` **boolean** (default false) - always include excerpts when serializing topic lists

- `csp_extensions` **string array** - add directives to the CSP. Works the same as the old “extend\_content\_security\_policy” theme-setting method. But remember, [simple `<script src="">` tags are allowed automatically](https://meta.discourse.org/t/automatically-adding-theme-scripts-to-csp/149028).

- `svg_icons` **string array** - a list of icons which should be included in the icon subset

- `topic thumbnails` **array of dimensions** - request additional resolutions in the topic thumbnail set. Note that they are generated asynchronously, so you must fall-back to the original image if your requested size is not provided. More information available [in the commit message](https://github.com/discourse/discourse/commit/03818e642a1ae871bffdc0c39c10f05f0b8b0398)

- `serialize_post_user_badges` **string array** - a list of badge names (matching entries in the badges table) to serialize alongside post data. When configured, the system includes the specified user badges with each post for client-side rendering.

One theme making heavy use of these new hooks is [Topic List Thumbnails](https://meta.discourse.org/t/topic-list-thumbnails-theme-component/150602) - check out the code to see how it works.

## Setting-dependent modifiers

Theme modifiers can also be configured to pull their value from a theme setting, allowing site operators to override modifier behavior without editing the theme’s code. To make a modifier depend on a setting, use this syntax in your `about.json`:

```json
{
  "modifiers": {
    "modifier_name": {
      "type": "setting",
      "value": "setting_name"
    }
  }
}

```

For example, if you have a theme setting called `show_excerpts` and want it to control the `serialize_topic_excerpts` modifier:

In `settings.yml`:

```yaml
show_excerpts:
  default: false

```

In `about.json`:

```json
{
  "modifiers": {
    "serialize_topic_excerpts": {
      "type": "setting",
      "value": "show_excerpts"
    }
  }
}

```

When the `show_excerpts` setting is changed, the modifier value will automatically update to match. This provides flexibility for site operators to customize theme behavior through the admin UI.

* * *

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

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 7, 2020, 5:16am UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/2 "2020-05-07T05:16:07Z")

</div>

David, probably a bit lazy of me to ask but is there any way to access this in a plugin:

`Themes can request additional thumbnail sizes by using a modifier in their about.json file:`

I will be attempting to migrate the TLP plugin to this new schema and it would be good to have the same access to features from a plugin, at least in the meantime.

---

<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: [May 7, 2020, 8:11am UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/3 "2020-05-07T08:11:10Z")

</div>

There isn’t at the moment, but I’ll look into it :eyes:

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 15, 2020, 2:15pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/6 "2020-05-15T14:15:57Z")

</div>

David, what’s the right approach for BULK recreation of thumbnails?

I’ve just tried utilising on one of my sites and it seems to have processed about 10% of the Topics … then given up (or turned its nose up at the rest). Why I think it’s the former is that the Topics for whom Thumbnails _were_ produced were the latest 10%.

Rebaking posts doesn’t seem to cut it. In fact, I did run a bulk rebake and wonder if that upset it …

I notice that image\_url can be populated, but there are no thumbnails.

Any advice, appreciated!

---

<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: [May 15, 2020, 2:28pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/7 "2020-05-15T14:28:47Z")

</div>

> [@merefield](#):
>
> image\_url can be populated

That column doesn’t do anything, and will be dropped very soon. image\_upload\_id is the one you want.

> [@merefield](#):
>
> BULK recreation of thumbnails?

There should be no need for this. I deliberately designed it so that people can install new themes without having to mess around on the console. Thumbnails are generated asynchronously when needed. For example:

- you add a new theme, which requests new resolutions
- a user requests a topic, we serve the thumbnails that exist. If any sizes don’t exist, we schedule a sidekiq job.
- next time someone requests the topic, the correct thumbnails will exist

If the requested thumbnail size is larger than the original, we won’t bother generate the thumbnail.

So the critical thing to bear in mind for this to work is:

> [@david](#):
>
> you must fall-back to the original image if your requested size is not provided.

There’s an example of this fallback logic in the thumbnail theme component I made - feel free to steal logic from there.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 15, 2020, 3:05pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/8 "2020-05-15T15:05:53Z")

</div>

The fallback is serialised as `thumbnailsl[0]`? Yes, I’m already handling that. (nice implementation btw, very easy to handle)

Is it possible some images are ‘not making the grade’ or fitting the criteria?

The behaviour we have in the TLP plugin will pick up one-box thumbnails. That’s not happening in every case here I _think_.

For example, if you get time, take a look at these examples:

> **[The 2020 MiRiDER ONE Folding eBike - UK built 2 year warranty](https://mirider.co.uk/2020-mirider-one-overview/?gclid=Cj0KCQjw7qn1BRDqARIsAKMbHDbX3dhbikC12-0GQDZLKgJCFw8NBj6GYfqbBDA7W5T7mBuyRHk8PCIaAsosEALw_wcB)**
>
> View our electric folding bike, the MiRiDER One, designed with a focus on making cycling fun, easy and accessible for everyone. Try the One for free today.

> **[Forget the Car. E-Scooters Could Save The City](https://www.wired.com/story/e-scooter-micromobility-infographics-cost-emissions/)**
>
> The vehicles made by Bird, Lime, and the like can slash emissions, reinvigorate mass transit, and address America’s dependency on cars.

[![](https://global.discourse-cdn.com/meta/original/4X/9/2/d/92d6076f158651723df3026820762db16f5d5dd1.jpeg "How to wash your hands NHS song | NHS") ](https://www.youtube.com/watch?v=S9VjeIWLnEg)

I don’t think these thumbnails make the cut. The thumbnails are serialized as null

---

<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: [May 15, 2020, 3:19pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/9 "2020-05-15T15:19:58Z")

</div>

> [@merefield](#):
>
> I don’t think these thumbnails make the cut

Yes that’s deliberate - we had a number of requests to remove small onebox thumbnails. For example, people were ending up with their github avatar as a topic thumbnail - which is rarely intended

[https://github.com/discourse/discourse/commit/956d15d13fd8056cbf60ca64ebbd1edca00d0125](https://github.com/discourse/discourse/commit/956d15d13fd8056cbf60ca64ebbd1edca00d0125)

Note that for oneboxes where the image is the actual content (such as instagram/twitter/etc photos), they will be selected.

As for the youtube video, I fixed that yesterday.

[https://github.com/discourse/discourse/commit/0c6f30d92a4090aa7447e2e579a17a180e49ce17](https://github.com/discourse/discourse/commit/0c6f30d92a4090aa7447e2e579a17a180e49ce17)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 15, 2020, 3:24pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/10 "2020-05-15T15:24:16Z")

</div>

Ah great, thanks for confirmation.

> [@david](#):
>
> As for the youtube video, I fixed that yesterday.

That’s odd, build was more recent, but some still seem to be being overlooked.

> [@david](#):
>
> Yes that’s deliberate - we had a number of requests to remove small onebox thumbnails. For example, people were ending up with their github avatar as a topic thumbnail - which is rarely intended

Yeah, that’s partly why I ended up implementing a thumbnail picker for the situations where the automated choice wasn’t optimal. I may still want to modify that behaviour, but I will try to do so in the plugin.

Thanks for your time David!

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 15, 2020, 6:34pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/11 "2020-05-15T18:34:47Z")

</div>

OK, I’ve worked it out. After a somewhat fruitless byebug session I could not work out why older YT posts were not getting thumbnails.

Then is dawned on me. It’s because of this:

 ![image](https://global.discourse-cdn.com/meta/original/3X/9/c/9cbaff13666c208aef63434cdc5d7ac1d9586e07.png)

So I suggest that actually it might be necessary to rebake after setting this to a rather larger number (365?).

I think I’m right in saying that if something is not uploaded locally, it won’t have a thumbnail created? …

---

<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: [May 15, 2020, 6:44pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/13 "2020-05-15T18:44:37Z")

</div>

> [@merefield](#):
>
> I think I’m right in saying that if something is not uploaded locally, it won’t have a thumbnail created?

:+1: correct, this only works for local uploads… we may need to rethink that “max days old” setting :thinking:

---

<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: [May 18, 2020, 8:35pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/15 "2020-05-18T20:35:52Z")

</div>

> [@Topic List Previews (legacy)](https://meta.discourse.org/t/topic-list-previews-legacy/101646/1007):
>
> would be great to have a plugin only option here

I have a plan, will try and get it implemented this week. One question - do you need the values to be dynamic?

i.e. Will the resolutions be defined at boot? Or at runtime (e.g. via site settings)?

The former is easier… but the latter might be possible as well :thinking:

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 18, 2020, 8:38pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/16 "2020-05-18T20:38:25Z")

</div>

Thanks for taking a look.

I just need a fixed way, exactly like the theme component.

A site setting would be nice though.

I will add for full disclosure: id like to migrate away from the plugin so parity with theme component solution would be more than enough.

---

<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: [May 19, 2020, 9:40am UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/17 "2020-05-19T09:40:04Z")

</div>

@merefield here you go:

[https://github.com/discourse/discourse/commit/725e38f9d7c42975c9d75afe0a1f79499693667b](https://github.com/discourse/discourse/commit/725e38f9d7c42975c9d75afe0a1f79499693667b)

Hopefully the commit message explains how it works, but let me know if you have any questions

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [May 19, 2020, 10:12am UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/18 "2020-05-19T10:12:06Z")

</div>

Excellent. Just added it to TLP and looks like it’s working! Thanks for your help!

---

<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: [June 8, 2020, 8:38am UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/19 "2020-06-08T08:38:24Z")

</div>

4 posts were split to a new topic: [Getting thumbnails from json endpoints](https://meta.discourse.org/t/getting-thumbnails-from-json-endpoints/154162)

---

<div class="post-metadata">

### Author: ![petepan23](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petepan23/32/161836_2.png) [@petepan23](https://meta.discourse.org/u/petepan23)
#### Post date: [July 3, 2020, 1:45pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/20 "2020-07-03T13:45:08Z")

</div>

Can we make it work for images from remote server as well? For example, images from Blogger, Picasa, or Amazon S3?

Because Discourse supports hosting on Amazon S3 for big and large image site, now if everything needs to be hosted on the local server directly then this design methodology seems to be a drawback.

With this update, it’s not an easy fix for my site since we’re using other server to host the images. Now it’s too difficult to move to an affiliated server with many posts, while it’s too big for hosting on local sever.

---

<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: [July 3, 2020, 2:12pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/21 "2020-07-03T14:12:07Z")

</div>

This is only designed to work on Discourse ‘uploads’. Those can be on S3, or some other service, if you use

> [@Configure an S3 compatible object storage provider for uploads](https://meta.discourse.org/t/using-object-storage-for-uploads-s3-clones/148916):
>
> information_source This topic covers how to configure some common S3 compatible Object Storage providers (S3 clones). See [Set up file and image uploads to S3](https://meta.discourse.org/t/setting-up-file-and-image-uploads-to-s3/7229) for more details about Amazon AWS S3 configuration, which is officially supported and used internally by Discourse for our hosting services. Provider Service Name Works with Discourse? [Amazon AWS](#aws-s3-2) S3 Yes [Digital Ocean](#digital-ocean-spaces-3) Spaces Yes [Linode](#linode-object-storage-4) Object Storage Yes [Google Cloud](#google-cloud-platform-storage-5) Storage Yes [Scaleway](#scaleway-object-storage-6) Object Storage Yes [Vultr](#vultr-object-storage-7) Obj…

We recommend using the `download_remote_images` site setting to automatically download images which are hotlinked from other sites.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [July 7, 2020, 8:25pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/22 "2020-07-07T20:25:28Z")

</div>

> [@david](#):
>
> `svg_icons` **string array** - a list of icons which should be included in the icon subset

Hi David, anything special one needs to do to ensure Pro icons can be used in a TC?

---

<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: [July 7, 2020, 9:58pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/23 "2020-07-07T21:58:21Z")

</div>

Nothing special, no. It should work just the same as using pro icons elsewhere in Discourse. I guess you are using [this plugin](https://meta.discourse.org/t/fontawesome-pro-icons/150871) to enable pro icons?

If it doesn’t work let me know and I’ll take a look :eyes:

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [July 7, 2020, 10:00pm UTC](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605/24 "2020-07-07T22:00:01Z")

</div>

Yep we are. We’ll have another dig. Thanks for response late your eve!

[Next page](https://meta.discourse.org/t/theme-modifiers-a-brief-introduction/150605.md?page=2)
