# Project Themes in 8.3

**URL:** <https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562>\
**Category:** Ignition 8.3 Early Access\
**Tags:** perspective\
**Created:** [May 22, 2025, 1:43pm UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562 "2025-05-22T13:43:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![darren.steele](https://avatars.discourse-cdn.com/v4/letter/d/a4c791/32.png) [@darren.steele](https://forum.inductiveautomation.com/u/darren.steele)\
**Post date:** [May 22, 2025, 1:43pm UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562/1 "2025-05-22T13:43:35Z")

</div>

Hi,

In 8.1 we just dropped the themes css files into the data/modules/com.inductiveautomation.perspective folder and everything just worked.

In 8.3 is it necessary to use the ThemeMigrator API? If so then I'm a bit stumped about how to get started. I read the Configurtion Migration guide [an old version at least - still can't access the latest version] and it seemed to hint that maybe themes was part of this new way of doing things but I didn't know where to begin.

Anybody got a suggestion about working with themes in 8.3 - preferably with a code example if APIs are involved.

Thanks

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 22, 2025, 3:59pm UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562/2 "2025-05-22T15:59:45Z")

</div>

Themes are now a part of the same standardized config system more or less everything is in 8.3.

You'll have to 'inject' your resources through the new configuration manager. You'll also have to make your module 'depend on' the Perspective module, if it isn't already, to get access to the `PerspectiveContext` and related classes.

I think something like this should work; there's one slightly unpleasant cast in the middle obscured in the `instanceof`, because the public type doesn't expose any modification actions, but this is a lot "cleaner" than dumping files on disk:

```python
        PerspectiveContext context = PerspectiveContext.get(gatewayContext);
        if (context.getThemeManager() instanceof NamedResourceHandler<?> themeManager) {
            themeManager.create("myCustomTheme", new ThemeConfig(null), "myCoolModule", builder -> {
                builder.putData("extraFile.css", ImmutableBytes.fromStream(myExtraFileInputStream));
            });
        }

```

---

<div class="post-metadata">

**Author:** ![mknowles](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/mknowles/32/70604_2.png) [@mknowles](https://forum.inductiveautomation.com/u/mknowles)\
**Post date:** [May 22, 2025, 8:08pm UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562/3 "2025-05-22T20:08:52Z")

</div>

Regarding the configuration management guide, that can be found here: [8.3 Early Access Now Available! - #3](https://forum.inductiveautomation.com/t/8-3-early-access-now-available/93932/3)

It's migrated to an internal doc, so we'll be adding pdf updates to the above post as needed.

---

<div class="post-metadata">

**Author:** ![darren.steele](https://avatars.discourse-cdn.com/v4/letter/d/a4c791/32.png) [@darren.steele](https://forum.inductiveautomation.com/u/darren.steele)\
**Post date:** [May 26, 2025, 11:36am UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562/4 "2025-05-26T11:36:11Z")

</div>

Hi Paul,

Thanks for your quick reply. The only way I could get your code to compile is if I used

```python
themeManager.create("kanoaTheme", null);

```

But this causes issues further down the line with:

```python
java.lang.NullPointerException: config object is required

```

If I use your code as it is above I get

```python
The method create(String, capture#5-of ?) in the type NamedResourceHandler<capture#5-of ?> is not applicable for the arguments (String, ThemeConfig)

```

I used a slightly different constructor just trying to get to the bottom of the reason that the create method doesn't like the ThemeConfig object. Kinda going around in circles here so any pointers would be very much appreciated.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 27, 2025, 3:28pm UTC](https://forum.inductiveautomation.com/t/project-themes-in-8-3/106562/5 "2025-05-27T15:28:28Z")

</div>

Probably type erasure of the generic. You'll have to do a technically-unsound cast to assure the compiler that the instance is the type you assert:

```python
PerspectiveContext context = PerspectiveContext.get(gatewayContext);
if (context.getThemeManager() instanceof NamedResourceHandler<?> genericManager) {
    NamedResourceManager<ThemeConfig> themeManager = (NamedResourceManager<ThemeConfig>) genericManager;
    themeManager.create("myCustomTheme", new ThemeConfig(null), "myCoolModule", builder -> {
        builder.putData("extraFile.css", ImmutableBytes.fromStream(myExtraFileInputStream));
    });
}

```
