Library / SDK
danieladov/jellyfin-plugin-skin-manager avatar
danieladov/jellyfin-plugin-skin-manager

jellyfin-plugin-skin-manager: a skin browser for the Jellyfin dashboard

Jellyfin Skin Manager is a plugin that helps you to download and install skins

675 stars41 forksJavaScriptMIT

At a glance

What is it?
Jellyfin Skin Manager is a dashboard plugin that lists downloadable skins and installs them with one click. It works by pulling skin definitions out of JSON catalogs and pushing the chosen CSS into the running web client, which means your reverse proxy policy can end up deciding whether it works at all.
Who is it for?
Use jellyfin-plugin-skin-manager if you run Jellyfin 10.8 or later and want to change the web client skin from the dashboard instead of editing files by hand. Skip it if you need per-user theming, native mobile app skins or plugin level JavaScript, since the catalog only carries CSS and a fixed set of option controls.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 172 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A plugin that turns skin swapping into a dashboard task

Jellyfin's web client ships with a fixed look out of the box, and changing it normally means dropping skin files into the right directory and editing configuration by hand. The Skin Manager plugin exists to remove that step. Its own description is plain about the scope: it is a plugin that helps you to download and install skins.

The plugin runs inside Jellyfin itself, appears as an entry in the Plugins area of the dashboard, and its whole user flow is three clicks. You open Skin Manager, select the skin you want, and click set skin. The plugin then downloads and installs that skin for you.

That narrowness is worth understanding before you install it. This is a skin browser and installer, not a theming framework. It does not introduce a new design system, a widget system or a layout editor. It also is not a separate service: there is no daemon to configure, no port to open and no environment variable to set. It shares the Jellyfin server process, which is why installation happens through the dashboard's plugin repository rather than a separate deployment.

The repository is a .NET solution, Jellyfin.Plugin.SkinManager.sln, with the plugin code under Jellyfin.Plugin.SkinManager/ and a src/ directory, and it is published under an MIT licence.

Skins are JSON descriptors, and the option model is fixed

The repository carries three skin catalogs at the top level, skins.json, skins-2.0.json and skins-3.0.json, which is the clearest hint about how the plugin works. A skin is not a binary bundle here. It is a JSON document that names the skin and describes the CSS that makes it look the way it does.

The documented skin properties are name for the skin name, author for the author, defaultCss for the base CSS, and options, an array of entries that modify the skin. Each option carries a type, one of checkBox, number, select or colorPicker, a name, a description and the css code that the option applies. Inside that css, the dollar symbol is replaced by the value the user picked, which applies to the number, select and colorPicker inputs. Number options can add default and step properties, and select options carry a selections array where each entry has a name and a value.

So the mechanism is a CSS injection layer with a small templating convention on top. The base stylesheet is applied first, then each option the user enables patches it, and the dollar placeholder is substituted with the chosen value. The catalogue of skins is what you would edit to add your own; the fixed set of four input types is the ceiling on what a skin can offer the user.

Installing from the plugin repository in four dashboard steps

The documented install path runs through Jellyfin's plugin repository mechanism. You open the dashboard, go to plugins, then Repositories, add the manifest link, search the Catalog for Skin Manager, install it and restart Jellyfin.

The manifest link to paste is a single URL:

bash
https://raw.githubusercontent.com/danieladov/JellyfinPluginManifest/master/manifest.json

The repository link points at the manifest in the JellyfinPluginManifest repository, which is where the package listing lives. Once the manifest is registered, Skin Manager shows up in the Catalog search, and the install plus the Jellyfin restart is all that is needed.

The restart is not optional in the documented flow. A plugin in Jellyfin loads as part of the server process, so the plugin only becomes available to the dashboard after the server comes back up. There is no separate activation step to remember after that.

If your Jellyfin installation cannot reach GitHub raw content, this path fails at the first step, and the manual install below is the fallback.

The zip route and building the dll yourself

The second install path avoids the manifest entirely. You download the .zip file from the release page, extract it, and place the .dll file in a folder called plugins/SkinManager under the program data directory or inside the portable install directory, then restart Jellyfin. Note the folder name and its capitalisation, since Jellyfin loads plugins from subdirectories of the plugins folder by their name.

The same target path is used when you build from source. Clone or download the repository, make sure you have the .NET Core SDK installed, then publish:

sh
dotnet publish --configuration Release --output bin

The publish output gives you the .dll that you then drop into plugins/SkinManager. Building it yourself is only useful if you want to change the skin catalogue or the option handling, since the shipped release binaries already contain the default catalogs.

The top level also holds install.bat for Windows and build.yaml, which appears to describe how the release artifacts are produced. The README does not document how to add a private catalogue file or a local skin source, so an unpublished skin is not something the documented workflow covers.

Content-Security-Policy is the reason the skin may not appear

If you run Jellyfin behind Nginx, the plugin may install a skin and still show nothing useful. The reason is the reverse proxy config published in the Jellyfin documentation. That config sets a Content-Security-Policy header, which the documentation describes as reducing the risk of XSS, and the policy restricts which external sources the client is allowed to load.

Skins frequently reference an external repository for images or assets and pull fonts from a CDN, so those URLs fall outside the default allowed list and the browser refuses them. The documented fix is to add the URL of the skin repository and the fonts to the list of allowed external sources. Each skin project documents its own requirements, and the example given is Kaleidochromic, which ships a guide for the reverse proxy setup.

One exception exists: the documentation notes that if you use the subpath configuration you can ignore all of this. So the subpath Nginx setup does not need the policy changes, while the default configuration does.

This is the sharpest operational edge in the project. The plugin can install successfully and still deliver a broken result, and the failure shows up in the browser console rather than in Jellyfin's logs.

Three catalog generations, and a release history with a long gap

The presence of skins.json, skins-2.0.json and skins-3.0.json tells you that skin definitions are versioned against the Jellyfin skin generation they target. The plugin therefore carries compatibility baggage that a simple CSS switch would not, and the catalogs are checked into the repository rather than fetched, so a skin added to the upstream catalogue only appears after a plugin update.

The release history shows how much movement there has been. Version 2.0.0, described as custom skin editor, new skins and more, dates to 2021-05-13. Version 2.0.1, which added Ultrachromic and a few fixes, dates to 2022-06-14. Version 2.0.2, a fix release, dates to 2024-11-04. The last push to the repository was on 2026-05-05, so work continues on the codebase even though the tagged releases are spaced far apart.

The licence is MIT, which is permissive for a plugin that you install into your own server, and the plugin is presented as part of the Jellyfin project in its README header. What the README does not document is a rollback path: there is no stated procedure for returning to a previous skin, and since skins are CSS applied to the client, a bad skin is usually cleared by selecting another one from the same list or by removing the plugin and restarting.

Editorial conclusion

Use jellyfin-plugin-skin-manager if you run Jellyfin 10.8 or later and want to change the web client skin from the dashboard instead of editing files by hand. Skip it if you need per-user theming, native mobile app skins or plugin level JavaScript, since the catalog only carries CSS and a fixed set of option controls. Before installing, confirm your reverse proxy Content-Security-Policy allows the skin repository URL and its fonts, and check that skins-2.0.json or skins-3.0.json matches the Jellyfin skin generation you run. The last push was on 2026-05-05 and the most recent tagged release is 2.0.2 from 2024-11-04.

Frequently asked questions

How do I install the Jellyfin Skin Manager plugin?

Add the manifest link in dashboard, plugins, Repositories, then find Skin Manager in the Catalog, install it and restart Jellyfin. You can also extract the .dll from the release .zip and place it in a folder named plugins/SkinManager under the program data directory or the portable install directory.

Why does my skin not load behind an Nginx reverse proxy?

The Nginx config from the Jellyfin documentation sets a Content-Security-Policy that restricts external sources, so the skin repository URL and its fonts get blocked. Add both to the allowed sources list, or use the subpath configuration, which the README says can ignore the issue.

What can a skin actually change in jellyfin-plugin-skin-manager?

A skin is a JSON document with a name, an author, a base CSS file and an array of options. The option types are limited to checkBox, number, select and colorPicker, and the dollar symbol in an option's css is replaced by the value the user chose.

How do I build jellyfin-plugin-skin-manager from source?

Clone the repository, install the .NET Core SDK, then run dotnet publish --configuration Release --output bin. Place the resulting .dll file in a folder called plugins/SkinManager under the program data directory or the portable install directory.

Official sources

  1. danieladov/jellyfin-plugin-skin-manager on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/danieladov-jellyfin-plugin-skin-manager.svg)](https://hysenlabs.com/projects/danieladov-jellyfin-plugin-skin-manager)

Was this useful?