Turn your Jellyfin server into a social film community.
Ten-star ratings and written reviews, Letterboxd-style user profiles, live chat and DMs, a full media request workflow, and a set of admin tools for keeping a large library tidy — all injected straight into the Jellyfin web UI, with no separate app to run.
Installation · Features · Configuration · API · Issues
📖 Illustrated field guide — the same tour with full-size screenshots
| Feature | What it does | |
|---|---|---|
| ⭐ | Star ratings | 1–10 stars on every item, per user, mirrored into Jellyfin's own rating fields |
| ✍️ | Written reviews | Reviews with likes, dislikes and threaded comments |
| 🏷️ | Card badges | Average score overlaid on poster cards, lazy-loaded for huge libraries |
| 🎬 | Netflix view | Horizontal genre rows with per-row sorting and reordering |
| 👤 | Social profiles | Letterboxd-style profiles: favourites, stats, taste graph, activity |
| 🤝 | Friends & follows | Friend requests, following, profile likes, blocking |
| 📋 | Custom lists | Build, reorder, clone and share film lists |
| 🟢 | Live presence | Online dots and a live "now watching" card |
| 💬 | Live chat & DMs | Public chat plus private messages, emoji and GIFs |
| 🛡️ | Moderator system | Three moderator tiers with quotas, limits and an action log |
| 📥 | Media requests | Fully customisable request form with a status workflow |
| 🗑️ | Deletion requests | Users nominate media for removal; admins approve or reject |
| 🚫 | User bans | Time-limited bans per request type |
| 🧹 | Media management | Scheduled deletion, disk usage, duplicates, trickplay cleanup, restarts |
| 📊 | Admin dashboard | Server-wide rating stats and activity in the Jellyfin sidebar |
| 🔔 | New media alerts | Grouped notifications when content lands |
| 🔍 | Smart search | Punctuation-insensitive search that respects library permissions |
| 🎨 | Deep theming | ~60 style settings for stars, header and review cards |
| 🌍 | 16 languages | Full UI translation, switchable per user |
| 💾 | Backup & restore | Export and re-import every piece of plugin data |
Everything is optional. Each subsystem can be switched off from the plugin settings page, and the plugin stays inert when disabled.
☕ If this plugin saves you time, makes your workflow easier, or helps you ship better code, consider buying me a coffee. Your support keeps the project alive and motivates me to keep building, improving, and hecking! 💻🐈 https://buymeacoffee.com/k3ntas
Hovering the stars — the value a click would submit follows the pointer, and the popup lists who rated what
A user profile: favourites, stats, rating distribution
Netflix-style browsing with per-genre rows and rating badges
The core of the plugin. A star row is injected above the title on every detail page — movies, series, seasons, episodes, music, anything Jellyfin can show.
MinRating / MaxRating).QuickRatingMode on, one click submits. With it off,
clicking opens a modal where a written review can be added alongside the score.8.0/10 - 12 ratings text under the stars, with a
configurable format string ({avg}, {count}, {s} for the plural suffix).Ratings do not stay locked inside the plugin:
UserData.Rating, so other tools —
Maintainerr, scripts, other clients — can read it through the standard Jellyfin API.
Non-destructive, and survives metadata refreshes. On by default.
Hovering the widget lists every user's score for that item. It shows scores only — never profile details — so it stays useful on a shared server without exposing anything.
A User Reviews section is added to each detail page, below the metadata.
The average score appears as a small badge on poster cards everywhere in Jellyfin — home rows, library grids, search results, collections.
IntersectionObserver, so only cards
actually on screen trigger a lookup, and lookups are batched into a single request.
An alternative way to browse a movie library: horizontal rows grouped by genre instead of one long alphabetical grid.
A search field in the header, replacing a trip to Jellyfin's own search page.
wall-e, wall e and walle all find the same film.
A header button (in place of Jellyfin's Sync Play button) opening a dropdown of the 50 most recently added items, with a badge showing how many are new since you last looked.
Popup notifications when something is added to the library.
DisplayMessage notifications.
From header button to profile, down through favourites, taste matching and the ratings tab
Every user gets a profile page in the style of Letterboxd, reachable from the header or by clicking any username.
Header — custom header media (image, GIF or video), avatar with a live online dot, member-since date, and a stat row: ratings, reviews, following, followers, likes.
Overview tab
Other tabs
| Tab | Contents |
|---|---|
| Ratings | Everything you have rated, as a poster wall with scores |
| Reviews | Your full review history |
| Activity | The complete activity log |
| Following / Followers | Who you follow and who follows you |
| Other Users | Everyone on the server, filterable, with friend badges |
The Ratings tab — everything you have scored, with the score under each poster
Personalisation — a style editor (palette icon) for your own profile colours, a settings panel for privacy, and a fullscreen toggle.
Four separate relationships, deliberately kept distinct:
A floating friends button gives quick access to who is online.
Build your own collections — "Best of 2026", "Comfort rewatches", anything.
Presence is delivered over a WebSocket connection, so it updates live rather than polling.

A chat window docked in the corner of the Jellyfin UI.
Chat moderation without handing out admin accounts. Three tiers, each with its own ceiling:
| Level | Can do | Bounded by |
|---|---|---|
| 1 | Delete messages, snooze users | Daily delete limit, fixed snooze duration |
| 2 | Everything above, plus temporary bans | Daily delete limit, maximum ban length in days |
| 3 | Everything above, plus media bans | Maximum media-ban days per user per month |
Pressing the header button, and the dialog stepping through its three tabs
A request workflow so users can ask for content without messaging you directly.
For users

Left: a request working through the queue. Right: the Watch Now button once it lands.
For admins
The pending-request count, shown on the header button
The other direction: users nominating things for removal to free up space.

Left: writing the rejection reason. Right: what a user sees once they hit the three-request limit.
Time-limited bans, applied per request type — someone can lose media-request rights while keeping deletion-request rights, or the reverse. Durations run from a day upwards, and active bans are listed with the option to lift them early.
Scheduled deletions, disk usage and the duplicate finder, in one dialog
An admin toolbox for keeping a large server healthy, opened from the header.
Scheduled deletion
Disk usage
Per-mount capacity with used/free/total and a fill bar, plus the combined totals.
Leftover trickplay cleanup
Trickplay tiles left behind by deleted media, in both places Jellyfin can store them: the
central trickplay directory and the .trickplay folders saved next to each video when a
library uses that setting. The panel reports exactly what it scanned and where, so "nothing
to clean up" can be told apart from a scan that never ran.
Duplicate finder
Finds items that exist more than once in the library and offers direct deletion.
Scheduled restart
Schedule a server restart with a countdown, cancellable while it is pending.
A dedicated page in the Jellyfin dashboard sidebar:
Export every piece of plugin data — ratings, reviews, requests, lists, profiles, chat history — as a single file, and import it back. The settings page tracks the date of your last backup and reminds you when it has been a while.
Roughly 60 settings dedicated purely to appearance, split into three groups on the settings page.
| Setting | Purpose |
|---|---|
StarWidgetBackground | Widget background, rgba supported |
StarWidgetBorderEnabled / StarWidgetBorderColor / StarWidgetBorderRadius | Border on/off, colour, corner radius |
StarWidgetGlowEffect / StarWidgetGlowColor | Outer glow and its colour |
StarFilledColor / StarEmptyColor / StarHoverColor | The three star states |
StarWidgetCustomCSS | Free-form CSS for animations and anything not covered above |
Background (or fully transparent), border colour and radius, icon colour and opacity, hover background, glow effect, overall group opacity, and separate control over the search field's background so it can match the group or stand apart.
Background and hover background, border on/off, colour and radius, username colour, timestamp colour, body text colour, rating colour, action-button colour and hover colour, liked and disliked colours, overall opacity, and whether hovering a reviewer shows a profile tooltip.
A JSON list of profiles, each matching a screen-width range:
[{ "minWidth": 0, "maxWidth": 1920, "offsetX": 0, "offsetY": 0,
"hideText": false, "sizePercent": 0, "removeBackground": false }]
The first profile whose range contains the current viewport width wins, so a phone, a laptop and a 4K television can each get badge placement that suits them.
The entire interface ships in 16 languages:
English · Español · 中文 · Português · Русский · 日本語 · Deutsch · Français · 한국어 · Italiano · Türkçe · Polski · Nederlands · العربية · हिन्दी · Lietuvių
Admins pick the server default; each user can override it from the header, and the choice persists in their browser. Language packs are served as separate, pre-compressed files so adding languages does not grow the main bundle.
Everything is configured from Dashboard → Plugins → Ratings → Settings. Each option carries its own explanation on the page itself; the sections are:
Rating System · UI Features · Social Features · Star Widget Styling · Badge Display Profiles · Header Button Group Styling · User Reviews Card Styling · Request Form (window, title, type, notes, IMDb code and IMDb link fields) · Custom Fields · Chat Notification Badge · Moderator System
| Setting | Default | Description |
|---|---|---|
EnableRatings | true | Master switch for the whole rating feature |
ShowCardRatingOverlay | true | Average-score badge on poster cards |
WriteRatingsToJellyfin | true | Mirror each rating into Jellyfin's native per-user rating |
WriteAverageToCommunityRating | false | Overwrite the item's community score with the plugin average ⚠️ |
MinRating / MaxRating | 1 / 10 | Rating range |
StarDisplayMode | 10-stars | 10-stars, 5-stars-half, or 5-stars |
QuickRatingMode | false | Submit on click instead of opening the review modal |
ShowRatingStats / RatingStatsFormat | false / {avg}/10 - {count} rating{s} | Stats line under the stars |
ShowYourRating / YourRatingFormat | false / — | "Your rating" line and its format |
EnableImdbSorting | true | Add IMDb sorting to the library sort dropdown |
| Setting | Default | Description |
|---|---|---|
DefaultLanguage | en | Server default UI language |
EnableNetflixView | true | Genre-row browsing on movie pages |
EnableRequestButton | true | Request Media button in the header |
ShowSearchButton / SearchExcludeEpisodes | true / true | Header search, and whether episodes are excluded |
ShowLanguageSwitch / ShowHeaderLanguageButton | true / true | Language switch in the request modal / header |
ShowNotificationToggle / NotificationsEnabledByDefault | true / true | Bell icon, and its default state |
ShowLatestMediaButton | true | Latest Media dropdown in the header |
ShowHeaderProfileButton | true | Profile button in the header |
HideHomeDuplicates | true | Suppress duplicate cards on the home page |
EnableNewMediaNotifications / EnableEpisodeGrouping | true / true | New-media popups, and episode grouping |
| Setting | Default | Description |
|---|---|---|
EnableFriendsButton | true | Floating friends button |
EnableChat | true | Live chat and DMs |
ChatMessageRetentionDays | 7 | How long messages are kept |
ChatRateLimitPerMinute | 10 | Messages per user per minute |
ChatMaxMessageLength | 500 | Characters per message |
ChatAllowGifs / ChatAllowEmojis | true / true | GIF and emoji support |
KlipyApiKey / TenorApiKey | — | GIF search provider key (Klipy is current, Tenor is legacy) |
ChatNotifyPublic / ChatNotifyPrivate | true / true | Notifications per message type |
ModLevel1DeleteLimit, ModLevel1SnoozeMinutes | — | Level 1 moderator ceilings |
ModLevel2DeleteLimit, ModLevel2TempBanMaxDays | — | Level 2 moderator ceilings |
ModLevel3MediaBanMaxDays | — | Level 3 media-ban ceiling |
ModeratorActionRateLimitPerMinute | — | Rate limit on moderator actions |
| Setting | Default | Description |
|---|---|---|
MaxRequestsPerMonth | 0 (unlimited) | Per-user monthly request quota |
AutoDeleteRejectedDays | 0 (off) | Auto-remove rejected requests after N days |
EnableAdminRequests | true | Let admins submit requests like users |
CustomRequestFields | — | Extra form fields, as JSON |
Request*Enabled / Request*Required / Request*Label / Request*Placeholder | — | Per-field control for title, type, notes, IMDb code and IMDb link |
RequestWindowTitle / RequestWindowDescription / RequestSubmitButtonText | — | Rewrite the modal's own wording |
EnableMediaManagement | true | Admin media tools |
DefaultDeletionDelayDays | 7 | Delay before a scheduled deletion runs |
AutoCancelDeletionThreshold | — | "Keep" requests needed to cancel a deletion (0 disables) |
| Setting | Description |
|---|---|
TmdbApiToken | TMDB v4 read access token, for poster fallback |
EnableExternalPosterFallback | Show a TMDB poster when Jellyfin has none |
TmdbLanguage | Language for TMDB titles and descriptions (e.g. en-US) |
Add the plugin repository
Dashboard → Plugins → Repositories → add:
https://raw.githubusercontent.com/K3ntas/jellyfin-plugin-ratings/main/manifest.json
Install
Plugins → Catalog → find Ratings → Install → restart Jellyfin.
That's it
The rating widget, header buttons and notification toggle appear automatically. Nothing needs configuring to get started — the defaults are sensible, and every feature can be tuned afterwards from the settings page.
Rating something — open any item, find the stars above the title, click. With quick mode off you get a modal where you can add a review; with it on the click is the rating.
Seeing who rated what — hover the star widget on a detail page.
Reviewing — write it in the rating modal, or edit it later from your profile's Reviews tab. Reviews appear under the item for everyone, and can be liked and commented on.
Requesting media — click the request button in the header, fill in the form, watch its status change from New through Processing to Done. A Watch Now button appears when it lands.
Requesting a deletion — from the item page. An admin approves or rejects it, and you see the reason either way.
Your profile — the person icon in the header. Add favourites by dragging or by searching any title, set your header media, and browse other users through the Other Users tab.
Chatting — the speech-bubble icon. The Public tab is the shared room; clicking a user anywhere opens a private tab with them.
Admin work — the folder icon opens Media Management, the request button opens the request queue with its ban controls, and the Ratings Dashboard lives in the Jellyfin sidebar.
flowchart LR
B["Jellyfin Web UI<br/>(browser)"] -->|injected| JS["ratings.js<br/>minified + brotli"]
JS -->|REST| API["Plugin controllers<br/>Ratings · Social · Chat"]
JS <-->|WebSocket| WS["Presence & chat<br/>listener"]
API --> REPO["Repositories<br/>coalesced writes"]
REPO --> JSONF[("JSON files<br/>plugin data dir")]
API --> JF["Jellyfin core<br/>library · users · sessions"]
NS["Library events"] --> API
IntersectionObserver and are fetched in batches.| Method | Route | Purpose |
|---|---|---|
POST | /Ratings/Items/{itemId}/Rating | Submit or update a rating |
DELETE | /Ratings/Items/{itemId}/Rating | Remove your rating |
GET | /Ratings/Items/{itemId}/Stats | Average and count for an item |
GET | /Ratings/Items/BatchStats | Stats for many items at once |
GET | /Ratings/Items/{itemId}/UserRating | Your rating for an item |
GET | /Ratings/Items/{itemId}/DetailedRatings | Every user's rating |
PUT | /Ratings/Items/{itemId}/Review | Write or edit a review |
POST | /Ratings/Reviews/{userId}/{itemId}/Like | Like or dislike a review |
GET POST | /Ratings/Reviews/{userId}/{itemId}/Comments | Read and post comments |
GET | /Ratings/Search · /Ratings/ExternalSearch | Library and external search |
GET | /Ratings/SortedLibrary · /Ratings/LatestMedia | Sorted browsing and latest items |
GET | /Ratings/Stats · /TopRated · /MostActiveUsers · /RatingDistribution | Dashboard data |
| Method | Route | Purpose |
|---|---|---|
GET POST | /Ratings/Requests | List and create media requests |
POST | /Ratings/Requests/{id}/Status · /Snooze · /Unsnooze | Request workflow |
GET POST | /Ratings/DeletionRequests | Deletion request queue |
GET POST DELETE | /Ratings/Bans | Ban management |
GET POST | /Ratings/Media · /Media/{id}/ScheduleDeletion | Scheduled deletion |
POST | /Ratings/KeepRequest/{itemId} | Ask to keep an item |
GET | /Ratings/Admin/DiskUsage · /Admin/Duplicates | Disk and duplicate tools |
GET POST | /Ratings/Admin/OrphanedTrickplay | Trickplay scan and cleanup |
POST DELETE | /Ratings/Admin/ScheduleRestart | Scheduled restarts |
GET POST | /Ratings/Backup/Export · /Backup/Import | Backup and restore |
Profiles (/Social/Profile/{userId} and its Full, Stats, Ratings, Reviews, Activity,
Genres, SimilarUsers, Lists, Followers, Following, FeaturedReviews variants),
friend requests, follows, profile likes, blocks, custom lists with reordering and cloning,
header media, profile styling, notifications, presence (Heartbeat, Watching, OnlineStatus),
privacy settings and presets, and IMDb id storage.
Public messages, direct messages and conversations, unread counts, typing indicators, online users, GIF search, moderator management with levels and statistics, action logs, bans, per-user styles and message quotas.
git clone https://github.com/K3ntas/jellyfin-plugin-ratings.git
cd jellyfin-plugin-ratings
dotnet build -c Release -p:RequireMinification=true
RequireMinification=true turns a missing Node/esbuild into a hard error rather than silently
shipping the unminified bundle. Continuous integration builds every push to main and dev,
verifies that minification actually ran, syntax-checks the JavaScript and validates the manifest.
├── Api/ # Controllers
│ ├── RatingsController.cs ratings, reviews, requests, admin tools
│ ├── SocialController.cs profiles, friends, lists, presence
│ ├── ChatController.cs public chat, DMs, moderation
│ └── SocialWebSocketListener.cs live presence and chat push
├── Data/ # JSON-backed repositories
├── Models/ # DTOs and stored entities
├── Web/
│ ├── ratings.js client bundle
│ ├── ratings.css stylesheet
│ └── i18n/ 16 language packs
├── Configuration/ # Settings page + PluginConfiguration
├── Pages/ # Dashboard pages
├── tools/compress-assets.js # Brotli + gzip generation
├── docs/ # Developer documentation
└── manifest.json # Plugin catalog manifest
Issues and pull requests are welcome — see the issue tracker. Security reports are covered by SECURITY.md.
Release notes for every version live on the
Releases page, and the plugin
catalog reads the same changelogs from manifest.json.
A note on the screenshots. They are taken from a live server. Usernames shown are pseudonyms; the library titles are genuine.
MIT — see LICENSE.
Built for the Jellyfin community. Thanks to everyone who has reported bugs, suggested features and contributed fixes.
JavaScript
45.5%
C#
35.9%
CSS
9.8%
HTML
8.8%
Turn your Jellyfin server into a social film community.
Ten-star ratings and written reviews, Letterboxd-style user profiles, live chat and DMs, a full media request workflow, and a set of admin tools for keeping a large library tidy — all injected straight into the Jellyfin web UI, with no separate app to run.
Installation · Features · Configuration · API · Issues
📖 Illustrated field guide — the same tour with full-size screenshots
| Feature | What it does | |
|---|---|---|
| ⭐ | Star ratings | 1–10 stars on every item, per user, mirrored into Jellyfin's own rating fields |
| ✍️ | Written reviews | Reviews with likes, dislikes and threaded comments |
| 🏷️ | Card badges | Average score overlaid on poster cards, lazy-loaded for huge libraries |
| 🎬 | Netflix view | Horizontal genre rows with per-row sorting and reordering |
| 👤 | Social profiles | Letterboxd-style profiles: favourites, stats, taste graph, activity |
| 🤝 | Friends & follows | Friend requests, following, profile likes, blocking |
| 📋 | Custom lists | Build, reorder, clone and share film lists |
| 🟢 | Live presence | Online dots and a live "now watching" card |
| 💬 | Live chat & DMs | Public chat plus private messages, emoji and GIFs |
| 🛡️ | Moderator system | Three moderator tiers with quotas, limits and an action log |
| 📥 | Media requests | Fully customisable request form with a status workflow |
| 🗑️ | Deletion requests | Users nominate media for removal; admins approve or reject |
| 🚫 | User bans | Time-limited bans per request type |
| 🧹 | Media management | Scheduled deletion, disk usage, duplicates, trickplay cleanup, restarts |
| 📊 | Admin dashboard | Server-wide rating stats and activity in the Jellyfin sidebar |
| 🔔 | New media alerts | Grouped notifications when content lands |
| 🔍 | Smart search | Punctuation-insensitive search that respects library permissions |
| 🎨 | Deep theming | ~60 style settings for stars, header and review cards |
| 🌍 | 16 languages | Full UI translation, switchable per user |
| 💾 | Backup & restore | Export and re-import every piece of plugin data |
Everything is optional. Each subsystem can be switched off from the plugin settings page, and the plugin stays inert when disabled.
☕ If this plugin saves you time, makes your workflow easier, or helps you ship better code, consider buying me a coffee. Your support keeps the project alive and motivates me to keep building, improving, and hecking! 💻🐈 https://buymeacoffee.com/k3ntas
Hovering the stars — the value a click would submit follows the pointer, and the popup lists who rated what
A user profile: favourites, stats, rating distribution
Netflix-style browsing with per-genre rows and rating badges
The core of the plugin. A star row is injected above the title on every detail page — movies, series, seasons, episodes, music, anything Jellyfin can show.
MinRating / MaxRating).QuickRatingMode on, one click submits. With it off,
clicking opens a modal where a written review can be added alongside the score.8.0/10 - 12 ratings text under the stars, with a
configurable format string ({avg}, {count}, {s} for the plural suffix).Ratings do not stay locked inside the plugin:
UserData.Rating, so other tools —
Maintainerr, scripts, other clients — can read it through the standard Jellyfin API.
Non-destructive, and survives metadata refreshes. On by default.
Hovering the widget lists every user's score for that item. It shows scores only — never profile details — so it stays useful on a shared server without exposing anything.
A User Reviews section is added to each detail page, below the metadata.
The average score appears as a small badge on poster cards everywhere in Jellyfin — home rows, library grids, search results, collections.
IntersectionObserver, so only cards
actually on screen trigger a lookup, and lookups are batched into a single request.
An alternative way to browse a movie library: horizontal rows grouped by genre instead of one long alphabetical grid.
A search field in the header, replacing a trip to Jellyfin's own search page.
wall-e, wall e and walle all find the same film.
A header button (in place of Jellyfin's Sync Play button) opening a dropdown of the 50 most recently added items, with a badge showing how many are new since you last looked.
Popup notifications when something is added to the library.
DisplayMessage notifications.
From header button to profile, down through favourites, taste matching and the ratings tab
Every user gets a profile page in the style of Letterboxd, reachable from the header or by clicking any username.
Header — custom header media (image, GIF or video), avatar with a live online dot, member-since date, and a stat row: ratings, reviews, following, followers, likes.
Overview tab
Other tabs
| Tab | Contents |
|---|---|
| Ratings | Everything you have rated, as a poster wall with scores |
| Reviews | Your full review history |
| Activity | The complete activity log |
| Following / Followers | Who you follow and who follows you |
| Other Users | Everyone on the server, filterable, with friend badges |
The Ratings tab — everything you have scored, with the score under each poster
Personalisation — a style editor (palette icon) for your own profile colours, a settings panel for privacy, and a fullscreen toggle.
Four separate relationships, deliberately kept distinct:
A floating friends button gives quick access to who is online.
Build your own collections — "Best of 2026", "Comfort rewatches", anything.
Presence is delivered over a WebSocket connection, so it updates live rather than polling.

A chat window docked in the corner of the Jellyfin UI.
Chat moderation without handing out admin accounts. Three tiers, each with its own ceiling:
| Level | Can do | Bounded by |
|---|---|---|
| 1 | Delete messages, snooze users | Daily delete limit, fixed snooze duration |
| 2 | Everything above, plus temporary bans | Daily delete limit, maximum ban length in days |
| 3 | Everything above, plus media bans | Maximum media-ban days per user per month |
Pressing the header button, and the dialog stepping through its three tabs
A request workflow so users can ask for content without messaging you directly.
For users

Left: a request working through the queue. Right: the Watch Now button once it lands.
For admins
The pending-request count, shown on the header button
The other direction: users nominating things for removal to free up space.

Left: writing the rejection reason. Right: what a user sees once they hit the three-request limit.
Time-limited bans, applied per request type — someone can lose media-request rights while keeping deletion-request rights, or the reverse. Durations run from a day upwards, and active bans are listed with the option to lift them early.
Scheduled deletions, disk usage and the duplicate finder, in one dialog
An admin toolbox for keeping a large server healthy, opened from the header.
Scheduled deletion
Disk usage
Per-mount capacity with used/free/total and a fill bar, plus the combined totals.
Leftover trickplay cleanup
Trickplay tiles left behind by deleted media, in both places Jellyfin can store them: the
central trickplay directory and the .trickplay folders saved next to each video when a
library uses that setting. The panel reports exactly what it scanned and where, so "nothing
to clean up" can be told apart from a scan that never ran.
Duplicate finder
Finds items that exist more than once in the library and offers direct deletion.
Scheduled restart
Schedule a server restart with a countdown, cancellable while it is pending.
A dedicated page in the Jellyfin dashboard sidebar:
Export every piece of plugin data — ratings, reviews, requests, lists, profiles, chat history — as a single file, and import it back. The settings page tracks the date of your last backup and reminds you when it has been a while.
Roughly 60 settings dedicated purely to appearance, split into three groups on the settings page.
| Setting | Purpose |
|---|---|
StarWidgetBackground | Widget background, rgba supported |
StarWidgetBorderEnabled / StarWidgetBorderColor / StarWidgetBorderRadius | Border on/off, colour, corner radius |
StarWidgetGlowEffect / StarWidgetGlowColor | Outer glow and its colour |
StarFilledColor / StarEmptyColor / StarHoverColor | The three star states |
StarWidgetCustomCSS | Free-form CSS for animations and anything not covered above |
Background (or fully transparent), border colour and radius, icon colour and opacity, hover background, glow effect, overall group opacity, and separate control over the search field's background so it can match the group or stand apart.
Background and hover background, border on/off, colour and radius, username colour, timestamp colour, body text colour, rating colour, action-button colour and hover colour, liked and disliked colours, overall opacity, and whether hovering a reviewer shows a profile tooltip.
A JSON list of profiles, each matching a screen-width range:
[{ "minWidth": 0, "maxWidth": 1920, "offsetX": 0, "offsetY": 0,
"hideText": false, "sizePercent": 0, "removeBackground": false }]
The first profile whose range contains the current viewport width wins, so a phone, a laptop and a 4K television can each get badge placement that suits them.
The entire interface ships in 16 languages:
English · Español · 中文 · Português · Русский · 日本語 · Deutsch · Français · 한국어 · Italiano · Türkçe · Polski · Nederlands · العربية · हिन्दी · Lietuvių
Admins pick the server default; each user can override it from the header, and the choice persists in their browser. Language packs are served as separate, pre-compressed files so adding languages does not grow the main bundle.
Everything is configured from Dashboard → Plugins → Ratings → Settings. Each option carries its own explanation on the page itself; the sections are:
Rating System · UI Features · Social Features · Star Widget Styling · Badge Display Profiles · Header Button Group Styling · User Reviews Card Styling · Request Form (window, title, type, notes, IMDb code and IMDb link fields) · Custom Fields · Chat Notification Badge · Moderator System
| Setting | Default | Description |
|---|---|---|
EnableRatings | true | Master switch for the whole rating feature |
ShowCardRatingOverlay | true | Average-score badge on poster cards |
WriteRatingsToJellyfin | true | Mirror each rating into Jellyfin's native per-user rating |
WriteAverageToCommunityRating | false | Overwrite the item's community score with the plugin average ⚠️ |
MinRating / MaxRating | 1 / 10 | Rating range |
StarDisplayMode | 10-stars | 10-stars, 5-stars-half, or 5-stars |
QuickRatingMode | false | Submit on click instead of opening the review modal |
ShowRatingStats / RatingStatsFormat | false / {avg}/10 - {count} rating{s} | Stats line under the stars |
ShowYourRating / YourRatingFormat | false / — | "Your rating" line and its format |
EnableImdbSorting | true | Add IMDb sorting to the library sort dropdown |
| Setting | Default | Description |
|---|---|---|
DefaultLanguage | en | Server default UI language |
EnableNetflixView | true | Genre-row browsing on movie pages |
EnableRequestButton | true | Request Media button in the header |
ShowSearchButton / SearchExcludeEpisodes | true / true | Header search, and whether episodes are excluded |
ShowLanguageSwitch / ShowHeaderLanguageButton | true / true | Language switch in the request modal / header |
ShowNotificationToggle / NotificationsEnabledByDefault | true / true | Bell icon, and its default state |
ShowLatestMediaButton | true | Latest Media dropdown in the header |
ShowHeaderProfileButton | true | Profile button in the header |
HideHomeDuplicates | true | Suppress duplicate cards on the home page |
EnableNewMediaNotifications / EnableEpisodeGrouping | true / true | New-media popups, and episode grouping |
| Setting | Default | Description |
|---|---|---|
EnableFriendsButton | true | Floating friends button |
EnableChat | true | Live chat and DMs |
ChatMessageRetentionDays | 7 | How long messages are kept |
ChatRateLimitPerMinute | 10 | Messages per user per minute |
ChatMaxMessageLength | 500 | Characters per message |
ChatAllowGifs / ChatAllowEmojis | true / true | GIF and emoji support |
KlipyApiKey / TenorApiKey | — | GIF search provider key (Klipy is current, Tenor is legacy) |
ChatNotifyPublic / ChatNotifyPrivate | true / true | Notifications per message type |
ModLevel1DeleteLimit, ModLevel1SnoozeMinutes | — | Level 1 moderator ceilings |
ModLevel2DeleteLimit, ModLevel2TempBanMaxDays | — | Level 2 moderator ceilings |
ModLevel3MediaBanMaxDays | — | Level 3 media-ban ceiling |
ModeratorActionRateLimitPerMinute | — | Rate limit on moderator actions |
| Setting | Default | Description |
|---|---|---|
MaxRequestsPerMonth | 0 (unlimited) | Per-user monthly request quota |
AutoDeleteRejectedDays | 0 (off) | Auto-remove rejected requests after N days |
EnableAdminRequests | true | Let admins submit requests like users |
CustomRequestFields | — | Extra form fields, as JSON |
Request*Enabled / Request*Required / Request*Label / Request*Placeholder | — | Per-field control for title, type, notes, IMDb code and IMDb link |
RequestWindowTitle / RequestWindowDescription / RequestSubmitButtonText | — | Rewrite the modal's own wording |
EnableMediaManagement | true | Admin media tools |
DefaultDeletionDelayDays | 7 | Delay before a scheduled deletion runs |
AutoCancelDeletionThreshold | — | "Keep" requests needed to cancel a deletion (0 disables) |
| Setting | Description |
|---|---|
TmdbApiToken | TMDB v4 read access token, for poster fallback |
EnableExternalPosterFallback | Show a TMDB poster when Jellyfin has none |
TmdbLanguage | Language for TMDB titles and descriptions (e.g. en-US) |
Add the plugin repository
Dashboard → Plugins → Repositories → add:
https://raw.githubusercontent.com/K3ntas/jellyfin-plugin-ratings/main/manifest.json
Install
Plugins → Catalog → find Ratings → Install → restart Jellyfin.
That's it
The rating widget, header buttons and notification toggle appear automatically. Nothing needs configuring to get started — the defaults are sensible, and every feature can be tuned afterwards from the settings page.
Rating something — open any item, find the stars above the title, click. With quick mode off you get a modal where you can add a review; with it on the click is the rating.
Seeing who rated what — hover the star widget on a detail page.
Reviewing — write it in the rating modal, or edit it later from your profile's Reviews tab. Reviews appear under the item for everyone, and can be liked and commented on.
Requesting media — click the request button in the header, fill in the form, watch its status change from New through Processing to Done. A Watch Now button appears when it lands.
Requesting a deletion — from the item page. An admin approves or rejects it, and you see the reason either way.
Your profile — the person icon in the header. Add favourites by dragging or by searching any title, set your header media, and browse other users through the Other Users tab.
Chatting — the speech-bubble icon. The Public tab is the shared room; clicking a user anywhere opens a private tab with them.
Admin work — the folder icon opens Media Management, the request button opens the request queue with its ban controls, and the Ratings Dashboard lives in the Jellyfin sidebar.
flowchart LR
B["Jellyfin Web UI<br/>(browser)"] -->|injected| JS["ratings.js<br/>minified + brotli"]
JS -->|REST| API["Plugin controllers<br/>Ratings · Social · Chat"]
JS <-->|WebSocket| WS["Presence & chat<br/>listener"]
API --> REPO["Repositories<br/>coalesced writes"]
REPO --> JSONF[("JSON files<br/>plugin data dir")]
API --> JF["Jellyfin core<br/>library · users · sessions"]
NS["Library events"] --> API
IntersectionObserver and are fetched in batches.| Method | Route | Purpose |
|---|---|---|
POST | /Ratings/Items/{itemId}/Rating | Submit or update a rating |
DELETE | /Ratings/Items/{itemId}/Rating | Remove your rating |
GET | /Ratings/Items/{itemId}/Stats | Average and count for an item |
GET | /Ratings/Items/BatchStats | Stats for many items at once |
GET | /Ratings/Items/{itemId}/UserRating | Your rating for an item |
GET | /Ratings/Items/{itemId}/DetailedRatings | Every user's rating |
PUT | /Ratings/Items/{itemId}/Review | Write or edit a review |
POST | /Ratings/Reviews/{userId}/{itemId}/Like | Like or dislike a review |
GET POST | /Ratings/Reviews/{userId}/{itemId}/Comments | Read and post comments |
GET | /Ratings/Search · /Ratings/ExternalSearch | Library and external search |
GET | /Ratings/SortedLibrary · /Ratings/LatestMedia | Sorted browsing and latest items |
GET | /Ratings/Stats · /TopRated · /MostActiveUsers · /RatingDistribution | Dashboard data |
| Method | Route | Purpose |
|---|---|---|
GET POST | /Ratings/Requests | List and create media requests |
POST | /Ratings/Requests/{id}/Status · /Snooze · /Unsnooze | Request workflow |
GET POST | /Ratings/DeletionRequests | Deletion request queue |
GET POST DELETE | /Ratings/Bans | Ban management |
GET POST | /Ratings/Media · /Media/{id}/ScheduleDeletion | Scheduled deletion |
POST | /Ratings/KeepRequest/{itemId} | Ask to keep an item |
GET | /Ratings/Admin/DiskUsage · /Admin/Duplicates | Disk and duplicate tools |
GET POST | /Ratings/Admin/OrphanedTrickplay | Trickplay scan and cleanup |
POST DELETE | /Ratings/Admin/ScheduleRestart | Scheduled restarts |
GET POST | /Ratings/Backup/Export · /Backup/Import | Backup and restore |
Profiles (/Social/Profile/{userId} and its Full, Stats, Ratings, Reviews, Activity,
Genres, SimilarUsers, Lists, Followers, Following, FeaturedReviews variants),
friend requests, follows, profile likes, blocks, custom lists with reordering and cloning,
header media, profile styling, notifications, presence (Heartbeat, Watching, OnlineStatus),
privacy settings and presets, and IMDb id storage.
Public messages, direct messages and conversations, unread counts, typing indicators, online users, GIF search, moderator management with levels and statistics, action logs, bans, per-user styles and message quotas.
git clone https://github.com/K3ntas/jellyfin-plugin-ratings.git
cd jellyfin-plugin-ratings
dotnet build -c Release -p:RequireMinification=true
RequireMinification=true turns a missing Node/esbuild into a hard error rather than silently
shipping the unminified bundle. Continuous integration builds every push to main and dev,
verifies that minification actually ran, syntax-checks the JavaScript and validates the manifest.
├── Api/ # Controllers
│ ├── RatingsController.cs ratings, reviews, requests, admin tools
│ ├── SocialController.cs profiles, friends, lists, presence
│ ├── ChatController.cs public chat, DMs, moderation
│ └── SocialWebSocketListener.cs live presence and chat push
├── Data/ # JSON-backed repositories
├── Models/ # DTOs and stored entities
├── Web/
│ ├── ratings.js client bundle
│ ├── ratings.css stylesheet
│ └── i18n/ 16 language packs
├── Configuration/ # Settings page + PluginConfiguration
├── Pages/ # Dashboard pages
├── tools/compress-assets.js # Brotli + gzip generation
├── docs/ # Developer documentation
└── manifest.json # Plugin catalog manifest
Issues and pull requests are welcome — see the issue tracker. Security reports are covered by SECURITY.md.
Release notes for every version live on the
Releases page, and the plugin
catalog reads the same changelogs from manifest.json.
A note on the screenshots. They are taken from a live server. Usernames shown are pseudonyms; the library titles are genuine.
MIT — see LICENSE.
Built for the Jellyfin community. Thanks to everyone who has reported bugs, suggested features and contributed fixes.
JavaScript
45.5%
C#
35.9%
CSS
9.8%
HTML
8.8%