A Jellyfin plugin that creates per-user virtual libraries for personalized Trakt recommendations and new seasons. Seamlessly integrates with Jellyseerr/Radarr/Sonarr/CustomWebhook to trigger one-click downloads directly from Jellyfin.
155
stars
65
commits
C#
primary language
Feb 24, 2026
updated
Features • Installation • Setup • Usage • Webhook Guide • Development
JellyNext brings Trakt-powered content discovery directly into your Jellyfin library. Each user can link their own Trakt account to get personalized recommendations and next season notifications through dedicated virtual libraries, with automatic one-click downloads via Radarr/Sonarr integration.
JellyNext is designed to work alongside the official Jellyfin Trakt plugin. However, you must exclude JellyNext virtual libraries from the official Trakt plugin to prevent unwanted scrobbling and updates to your Trakt account.
Important Configuration:
Trakt Movie RecommendationsTrakt Show RecommendationsTrakt Next SeasonsTrending Movies (if enabled)Per-User Libraries:
Global Libraries (shared across all users):
Features:
[tmdbid-X], [tvdbid-X])Add Plugin Repository to Jellyfin
https://raw.githubusercontent.com/luall0/jellyfin-luall0-plugins/refs/heads/main/manifest.jsonInstall JellyNext Plugin
Verify Installation
Download the Plugin
jellynext-vX.X.X.zip from ReleasesExtract to Jellyfin Plugins Directory
/var/lib/jellyfin/plugins/JellyNext_vX.X.X/%AppData%\Jellyfin\Server\plugins\JellyNext_vX.X.X\/config/plugins/JellyNext_vX.X.X/Note: The version folder name (e.g., JellyNext_v1.0.0) is important for Jellyfin's plugin system.
Restart Jellyfin
Each Jellyfin user must link their own Trakt account for personalized recommendations.
Navigate to: Dashboard → Plugins → JellyNext
Start Authorization
Device Code Appears
ABC12345 will be displayedActivate on Trakt
Verification
After authorization, configure what to sync for each user:
Content Sync Options:
Watchlist Sync Options:
Recommendation Limits:
Filtering Options:
Performance Options:
Debugging:
Click Save after making changes.
For each user who will use JellyNext, create three Jellyfin libraries pointing to the virtual folders.
Go to: Dashboard → Libraries → Add Media Library
Create three libraries with these exact settings:
MoviesTrakt Movie Recommendations (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/movies-recommendations/ShowsTrakt Show Recommendations (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/shows-recommendations/ShowsTrakt Next Seasons (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/next-seasons/Finding your user ID:
a1b2c3d4e5f6...)/jellyfin/data/jellynext-virtual/ will contain user foldersImportant Notes:
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: JellyNext Virtual Libraries Initialized
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: IMPORTANT: Each content type is a SEPARATE library in Jellyfin
VirtualLibraryManager: (e.g., "admin's Movies Recommendations", "admin's Shows Recommendations")
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: User ID: 8ed9b676-f57a-4483-8def-f36d0515de83
VirtualLibraryManager: [1] Movie Recommendations:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/movies_recommendations
VirtualLibraryManager: Library Type: Movies
VirtualLibraryManager: Suggested Name: "[Your Username]'s Movies Recommendations"
VirtualLibraryManager: [2] Show Recommendations:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/shows_recommendations
VirtualLibraryManager: Library Type: Shows
VirtualLibraryManager: Suggested Name: "[Your Username]'s Shows Recommendations"
VirtualLibraryManager: [3] Next Seasons:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/shows_nextseasons
VirtualLibraryManager: Library Type: Shows
VirtualLibraryManager: Suggested Name: "[Your Username]'s Next Seasons"
VirtualLibraryManager: Setup Instructions:
VirtualLibraryManager: 1. Go to Jellyfin Dashboard → Libraries → Add Media Library
VirtualLibraryManager: 2. For EACH content type above, create a SEPARATE library:
VirtualLibraryManager: - Select content type (Movies or Shows)
VirtualLibraryManager: - Add the folder path shown above
VirtualLibraryManager: - Use the suggested library name
VirtualLibraryManager: 3. This allows you to have separate libraries per recommendation type
VirtualLibraryManager: --------------------------------------------------------------------------------
/config/data/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/...)After linking Trakt and adding virtual libraries:
Wait for automatic sync (happens 5 seconds after Jellyfin starts, then every 6 hours)
OR
Manually trigger sync:
Monitor Progress:
.strm filesVerify Libraries:
If you want to enable automatic downloads when clicking "Play" on virtual library items, choose one of three integration modes:
Navigate to: Dashboard → Plugins → JellyNext → Download Integration
Option A: Jellyseerr Integration (Recommended for Multi-User)
Use this if you want centralized request management, approval workflows, and multi-user request tracking.
http://localhost:5055 or http://jellyseerr:5055 for Docker)Configuration Mode:
Use Jellyseerr Defaults (Recommended):
Manual Configuration:
Jellyseerr Features:
Option B: Native Radarr/Sonarr Integration
Use this for direct integration without Jellyseerr (simpler setup, but no approval workflows).
Radarr Configuration:
http://localhost:7878 or http://radarr:7878 for Docker)Sonarr Configuration:
http://localhost:8989 or http://sonarr:8989 for Docker)Option C: Webhook Integration (Advanced)
Use this for custom integrations with external systems, notification services, or non-Radarr/Sonarr download systems.
Webhook Features:
📖 Read the full Webhook Integration Guide →
Click Save when done.
After setup, you'll see three new libraries per user:
Trakt Movie Recommendations
Trakt Show Recommendations
Trakt Next Seasons
When enabled, JellyNext automatically monitors your Trakt watchlist and adds items to your download system:
To enable: Go to Dashboard → Plugins → JellyNext → Trakt tab, select a user, and check "Sync Watchlist Movies" and/or "Sync Watchlist Shows".
Note: Watchlist sync requires a download integration to be configured (Native, Jellyseerr, or Webhook).
How It Works:
When you click "Play" on any virtual library item, the plugin automatically:
Detects the playback attempt on a virtual item
Identifies the content (movie vs TV show, season number, IDs)
Routes to the configured integration:
Jellyseerr Mode:
Native Mode:
Webhook Mode:
Adds to download queue with your configured quality profile (or triggers your custom webhook)
Prevents "watched" marking by clearing playback state
For TV Shows:
After Download:
Request Tracking (Jellyseerr Only):
User clicks Play → PlaybackInterceptor detects virtual path
↓
Extracts IDs (TMDB/TVDB) and season info
↓
Looks up cached metadata
↓
Calls RadarrService or SonarrService
↓
Adds to download queue
↓
Sends notification to user
↓
Waits 2 seconds (configurable)
↓
Stops playback & clears "watched" status
This all happens in seconds, mostly invisible to the user.
When you click "Play" on a virtual library item, JellyNext triggers the download and then automatically stops playback. Here's what you need to know:
What You'll See:
Client Compatibility:
If Playback Doesn't Stop Automatically:
Why the Delay?
Client Support: If your client doesn't support automatic playback stop, this is a Jellyfin native feature limitation. You can:
Important: The download is triggered immediately when you click "Play" - the playback stop is just to prevent the dummy video from playing. Even if playback doesn't stop automatically, the download has already been added to Radarr/Sonarr.
# Clone the repository
git clone https://github.com/luall0/jellynext.git
cd jellynext
# Restore dependencies
dotnet restore Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Build the plugin (Debug)
dotnet build Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Build for release
dotnet build -c Release Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Output will be in: Jellyfin.Plugin.JellyNext/bin/Release/net9.0/
Jellyfin.Plugin.JellyNext/
├── Api/ # REST API Controllers
│ ├── TraktController.cs # OAuth flow, user management, settings
│ ├── JellyseerrController.cs # Jellyseerr connection testing, server/profile retrieval
│ ├── RadarrController.cs # Radarr connection testing, profiles (native mode)
│ ├── SonarrController.cs # Sonarr connection testing, profiles (native mode)
│ └── JellyNextLibraryController.cs # Query cached content
├── Configuration/ # Plugin settings
│ ├── PluginConfiguration.cs # Settings model (persisted)
│ └── configPage.html # Admin web UI
├── Helpers/ # Utility classes
│ └── UserHelper.cs # User configuration lookups
├── Models/ # Data models organized by service
│ ├── Common/ # ContentItem, ContentType, DownloadResult
│ ├── Jellyseerr/ # MediaRequest, JellyseerrUser, RadarrServer, SonarrServer
│ ├── Trakt/ # TraktUser, TraktMovie, TraktShow, OAuth models
│ ├── Radarr/ # Movie, QualityProfile, RootFolder
│ └── Sonarr/ # Series, Season, QualityProfile
├── Providers/ # Pluggable content sources
│ ├── IContentProvider.cs # Provider interface
│ ├── RecommendationsProvider.cs # Trakt recommendations
│ └── NextSeasonsProvider.cs # Next season notifications
├── Resources/ # Embedded resources
│ ├── dummy.mp4 # 1-hour FFprobe-compatible video (prevents "watched")
│ └── dummy_short.mp4 # 2-second video (auto-stops playback)
├── ScheduledTasks/ # Background tasks
│ └── ContentSyncScheduledTask.cs # Periodic sync (6hr default)
├── Services/ # Business logic
│ ├── TraktApi.cs # Trakt API client (OAuth, recommendations)
│ ├── ContentSyncService.cs # Orchestrates sync across users/providers
│ ├── ContentCacheService.cs # In-memory content cache (6hr expiration)
│ ├── ShowsCacheService.cs # Season-level cache for TV shows with incremental sync
│ ├── LocalLibraryService.cs # Jellyfin library queries
│ ├── PlaybackInterceptor.cs # Detects virtual playback, routes to download provider
│ ├── JellyseerrService.cs # Jellyseerr API client (user import, requests)
│ ├── RadarrService.cs # Radarr API client (native mode)
│ ├── SonarrService.cs # Sonarr API client (native mode, anime detection)
│ └── DownloadProviders/ # Download provider implementations
│ ├── IDownloadProvider.cs # Provider interface
│ ├── JellyseerrDownloadProvider.cs # Jellyseerr integration
│ ├── NativeDownloadProvider.cs # Direct Radarr/Sonarr integration
│ ├── WebhookDownloadProvider.cs # Custom webhook integration
│ └── DownloadProviderFactory.cs # Provider selection
├── VirtualLibrary/ # Virtual library system
│ ├── VirtualLibraryManager.cs # Stub file creation/management
│ ├── VirtualLibraryCreator.cs # Initialization
│ ├── VirtualLibraryContentType.cs # Enum of content types
│ └── VirtualLibraryContentTypeHelper.cs # Type mappings
├── Plugin.cs # Plugin entry point (singleton)
└── PluginServiceRegistrator.cs # Dependency injection setup
Key Design Patterns:
Provider System: Pluggable content sources via IContentProvider interface
Per-User Architecture: Each user has isolated configuration
Smart Caching: Multiple cache layers
Download Provider Pattern: Pluggable download backends
IDownloadProvider interface for extensibilityNativeDownloadProvider: Direct Radarr/Sonarr API callsJellyseerrDownloadProvider: Routes through Jellyseerr APIWebhookDownloadProvider: Custom HTTP webhook integrationPlayback Interception: Event-driven download triggers
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)git push origin feature/amazing-feature)Critical Implementation Details:
NamedClient.Default for Trakt API (avoids Cloudflare blocks)trakt-api-version: 2 and trakt-api-key headers (no User-Agent/Accept)extended=full on Trakt endpoints to get genre data for anime detectionUser entity (not Guid), use IUserManager.GetUserById()"Plugin not appearing after restart"
JellyNext_v1.0.0 (not just JellyNext)"Libraries showing as empty"
/jellyfin/data/jellynext-virtual/[user-id]/[content-type]/"Authorization stuck on 'Waiting...'"
"Token refresh failing"
"Cloudflare blocking requests"
NamedClient.Default"No recommendations appearing"
"Virtual libraries not updating"
"Too many API calls to Trakt"
"Downloads not triggering"
"Downloads trigger but fail"
[tmdbid-12345])"Anime not going to anime folder/profile"
"User not being imported to Jellyseerr"
"Item marked as watched after download attempt"
"Jellyfin library scans taking too long"
"High memory usage"
Enable Extra Logging:
Useful Log Locations:
Q: Do I need a Trakt VIP subscription? A: No, JellyNext works with free Trakt accounts.
Q: Will this download content automatically? A: By default, downloads are triggered only when you click "Play" on a virtual library item (one-click). However, you can enable Watchlist Sync to automatically add Trakt watchlisted items to your download system.
Q: Can I use this without Radarr/Sonarr/Jellyseerr? A: Yes, you can still use the virtual libraries to browse recommendations. Downloads just won't work.
Q: Which integration mode should I use? A:
Q: Do I need both Jellyseerr AND Radarr/Sonarr? A: If using Jellyseerr mode, you only need to configure Jellyseerr. Jellyseerr then communicates with Radarr/Sonarr. In Native mode, you configure Radarr/Sonarr directly. In Webhook mode, you configure your own custom endpoint.
Q: Can I integrate with systems other than Radarr/Sonarr? A: Yes! Use Webhook mode to integrate with any system that accepts HTTP requests. See the Webhook Integration Guide for examples.
Q: Does this affect my real Jellyfin libraries? A: No, virtual libraries are completely separate. They don't modify or interfere with your existing media.
Q: Can multiple users use this on the same Jellyfin server? A: Yes! Each user links their own Trakt account and gets their own virtual libraries with personalized recommendations.
Q: How often does it sync with Trakt? A: Default is every 6 hours. Configurable via "Cache Expiration (hours)" setting.
Q: What's the difference between Show Recommendations and Next Seasons? A:
Q: Why only 10 seasons for show recommendations? A: Performance. Jellyfin scans can be slow with thousands of stub files. Enable "Limit Shows to Season 1" for even better performance.
Q: How does anime detection work? A: Plugin checks if Trakt metadata includes "anime" genre, then routes to your configured anime root folder in Sonarr.
Q: Can I customize which recommendations appear? A: Yes, via per-user settings:
Q: How does Watchlist Sync work? A: When enabled, JellyNext checks your Trakt watchlist every hour and automatically adds new items to your configured download system (Radarr/Sonarr, Jellyseerr, or Webhook). Items already in your Jellyfin library or previously processed are skipped. Enable it per-user in the Trakt user settings.
Q: Does this use my Jellyfin API key? A: No, it uses Trakt's OAuth system. Each user authorizes the plugin via Trakt's website.
Q: Is this an official Jellyfin plugin? A: Not yet. It's currently community-maintained. Official repository submission planned for future.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Copyright (C) 2025 luall0
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
65 commits
C#
76.0%
HTML
12.2%
JavaScript
11.7%
A Jellyfin plugin that creates per-user virtual libraries for personalized Trakt recommendations and new seasons. Seamlessly integrates with Jellyseerr/Radarr/Sonarr/CustomWebhook to trigger one-click downloads directly from Jellyfin.
155
stars
65
commits
C#
primary language
Feb 24, 2026
updated
Features • Installation • Setup • Usage • Webhook Guide • Development
JellyNext brings Trakt-powered content discovery directly into your Jellyfin library. Each user can link their own Trakt account to get personalized recommendations and next season notifications through dedicated virtual libraries, with automatic one-click downloads via Radarr/Sonarr integration.
JellyNext is designed to work alongside the official Jellyfin Trakt plugin. However, you must exclude JellyNext virtual libraries from the official Trakt plugin to prevent unwanted scrobbling and updates to your Trakt account.
Important Configuration:
Trakt Movie RecommendationsTrakt Show RecommendationsTrakt Next SeasonsTrending Movies (if enabled)Per-User Libraries:
Global Libraries (shared across all users):
Features:
[tmdbid-X], [tvdbid-X])Add Plugin Repository to Jellyfin
https://raw.githubusercontent.com/luall0/jellyfin-luall0-plugins/refs/heads/main/manifest.jsonInstall JellyNext Plugin
Verify Installation
Download the Plugin
jellynext-vX.X.X.zip from ReleasesExtract to Jellyfin Plugins Directory
/var/lib/jellyfin/plugins/JellyNext_vX.X.X/%AppData%\Jellyfin\Server\plugins\JellyNext_vX.X.X\/config/plugins/JellyNext_vX.X.X/Note: The version folder name (e.g., JellyNext_v1.0.0) is important for Jellyfin's plugin system.
Restart Jellyfin
Each Jellyfin user must link their own Trakt account for personalized recommendations.
Navigate to: Dashboard → Plugins → JellyNext
Start Authorization
Device Code Appears
ABC12345 will be displayedActivate on Trakt
Verification
After authorization, configure what to sync for each user:
Content Sync Options:
Watchlist Sync Options:
Recommendation Limits:
Filtering Options:
Performance Options:
Debugging:
Click Save after making changes.
For each user who will use JellyNext, create three Jellyfin libraries pointing to the virtual folders.
Go to: Dashboard → Libraries → Add Media Library
Create three libraries with these exact settings:
MoviesTrakt Movie Recommendations (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/movies-recommendations/ShowsTrakt Show Recommendations (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/shows-recommendations/ShowsTrakt Next Seasons (or your choice)/path/to/jellyfin/data/jellynext-virtual/[user-id]/next-seasons/Finding your user ID:
a1b2c3d4e5f6...)/jellyfin/data/jellynext-virtual/ will contain user foldersImportant Notes:
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: JellyNext Virtual Libraries Initialized
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: IMPORTANT: Each content type is a SEPARATE library in Jellyfin
VirtualLibraryManager: (e.g., "admin's Movies Recommendations", "admin's Shows Recommendations")
VirtualLibraryManager: ================================================================================
VirtualLibraryManager: User ID: 8ed9b676-f57a-4483-8def-f36d0515de83
VirtualLibraryManager: [1] Movie Recommendations:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/movies_recommendations
VirtualLibraryManager: Library Type: Movies
VirtualLibraryManager: Suggested Name: "[Your Username]'s Movies Recommendations"
VirtualLibraryManager: [2] Show Recommendations:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/shows_recommendations
VirtualLibraryManager: Library Type: Shows
VirtualLibraryManager: Suggested Name: "[Your Username]'s Shows Recommendations"
VirtualLibraryManager: [3] Next Seasons:
VirtualLibraryManager: Path: /config/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/8ed9b676-f57a-4483-8def-f36d0515de83/shows_nextseasons
VirtualLibraryManager: Library Type: Shows
VirtualLibraryManager: Suggested Name: "[Your Username]'s Next Seasons"
VirtualLibraryManager: Setup Instructions:
VirtualLibraryManager: 1. Go to Jellyfin Dashboard → Libraries → Add Media Library
VirtualLibraryManager: 2. For EACH content type above, create a SEPARATE library:
VirtualLibraryManager: - Select content type (Movies or Shows)
VirtualLibraryManager: - Add the folder path shown above
VirtualLibraryManager: - Use the suggested library name
VirtualLibraryManager: 3. This allows you to have separate libraries per recommendation type
VirtualLibraryManager: --------------------------------------------------------------------------------
/config/data/plugins/Jellyfin.Plugin.JellyNext/jellynext-virtual/...)After linking Trakt and adding virtual libraries:
Wait for automatic sync (happens 5 seconds after Jellyfin starts, then every 6 hours)
OR
Manually trigger sync:
Monitor Progress:
.strm filesVerify Libraries:
If you want to enable automatic downloads when clicking "Play" on virtual library items, choose one of three integration modes:
Navigate to: Dashboard → Plugins → JellyNext → Download Integration
Option A: Jellyseerr Integration (Recommended for Multi-User)
Use this if you want centralized request management, approval workflows, and multi-user request tracking.
http://localhost:5055 or http://jellyseerr:5055 for Docker)Configuration Mode:
Use Jellyseerr Defaults (Recommended):
Manual Configuration:
Jellyseerr Features:
Option B: Native Radarr/Sonarr Integration
Use this for direct integration without Jellyseerr (simpler setup, but no approval workflows).
Radarr Configuration:
http://localhost:7878 or http://radarr:7878 for Docker)Sonarr Configuration:
http://localhost:8989 or http://sonarr:8989 for Docker)Option C: Webhook Integration (Advanced)
Use this for custom integrations with external systems, notification services, or non-Radarr/Sonarr download systems.
Webhook Features:
📖 Read the full Webhook Integration Guide →
Click Save when done.
After setup, you'll see three new libraries per user:
Trakt Movie Recommendations
Trakt Show Recommendations
Trakt Next Seasons
When enabled, JellyNext automatically monitors your Trakt watchlist and adds items to your download system:
To enable: Go to Dashboard → Plugins → JellyNext → Trakt tab, select a user, and check "Sync Watchlist Movies" and/or "Sync Watchlist Shows".
Note: Watchlist sync requires a download integration to be configured (Native, Jellyseerr, or Webhook).
How It Works:
When you click "Play" on any virtual library item, the plugin automatically:
Detects the playback attempt on a virtual item
Identifies the content (movie vs TV show, season number, IDs)
Routes to the configured integration:
Jellyseerr Mode:
Native Mode:
Webhook Mode:
Adds to download queue with your configured quality profile (or triggers your custom webhook)
Prevents "watched" marking by clearing playback state
For TV Shows:
After Download:
Request Tracking (Jellyseerr Only):
User clicks Play → PlaybackInterceptor detects virtual path
↓
Extracts IDs (TMDB/TVDB) and season info
↓
Looks up cached metadata
↓
Calls RadarrService or SonarrService
↓
Adds to download queue
↓
Sends notification to user
↓
Waits 2 seconds (configurable)
↓
Stops playback & clears "watched" status
This all happens in seconds, mostly invisible to the user.
When you click "Play" on a virtual library item, JellyNext triggers the download and then automatically stops playback. Here's what you need to know:
What You'll See:
Client Compatibility:
If Playback Doesn't Stop Automatically:
Why the Delay?
Client Support: If your client doesn't support automatic playback stop, this is a Jellyfin native feature limitation. You can:
Important: The download is triggered immediately when you click "Play" - the playback stop is just to prevent the dummy video from playing. Even if playback doesn't stop automatically, the download has already been added to Radarr/Sonarr.
# Clone the repository
git clone https://github.com/luall0/jellynext.git
cd jellynext
# Restore dependencies
dotnet restore Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Build the plugin (Debug)
dotnet build Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Build for release
dotnet build -c Release Jellyfin.Plugin.JellyNext/Jellyfin.Plugin.JellyNext.csproj
# Output will be in: Jellyfin.Plugin.JellyNext/bin/Release/net9.0/
Jellyfin.Plugin.JellyNext/
├── Api/ # REST API Controllers
│ ├── TraktController.cs # OAuth flow, user management, settings
│ ├── JellyseerrController.cs # Jellyseerr connection testing, server/profile retrieval
│ ├── RadarrController.cs # Radarr connection testing, profiles (native mode)
│ ├── SonarrController.cs # Sonarr connection testing, profiles (native mode)
│ └── JellyNextLibraryController.cs # Query cached content
├── Configuration/ # Plugin settings
│ ├── PluginConfiguration.cs # Settings model (persisted)
│ └── configPage.html # Admin web UI
├── Helpers/ # Utility classes
│ └── UserHelper.cs # User configuration lookups
├── Models/ # Data models organized by service
│ ├── Common/ # ContentItem, ContentType, DownloadResult
│ ├── Jellyseerr/ # MediaRequest, JellyseerrUser, RadarrServer, SonarrServer
│ ├── Trakt/ # TraktUser, TraktMovie, TraktShow, OAuth models
│ ├── Radarr/ # Movie, QualityProfile, RootFolder
│ └── Sonarr/ # Series, Season, QualityProfile
├── Providers/ # Pluggable content sources
│ ├── IContentProvider.cs # Provider interface
│ ├── RecommendationsProvider.cs # Trakt recommendations
│ └── NextSeasonsProvider.cs # Next season notifications
├── Resources/ # Embedded resources
│ ├── dummy.mp4 # 1-hour FFprobe-compatible video (prevents "watched")
│ └── dummy_short.mp4 # 2-second video (auto-stops playback)
├── ScheduledTasks/ # Background tasks
│ └── ContentSyncScheduledTask.cs # Periodic sync (6hr default)
├── Services/ # Business logic
│ ├── TraktApi.cs # Trakt API client (OAuth, recommendations)
│ ├── ContentSyncService.cs # Orchestrates sync across users/providers
│ ├── ContentCacheService.cs # In-memory content cache (6hr expiration)
│ ├── ShowsCacheService.cs # Season-level cache for TV shows with incremental sync
│ ├── LocalLibraryService.cs # Jellyfin library queries
│ ├── PlaybackInterceptor.cs # Detects virtual playback, routes to download provider
│ ├── JellyseerrService.cs # Jellyseerr API client (user import, requests)
│ ├── RadarrService.cs # Radarr API client (native mode)
│ ├── SonarrService.cs # Sonarr API client (native mode, anime detection)
│ └── DownloadProviders/ # Download provider implementations
│ ├── IDownloadProvider.cs # Provider interface
│ ├── JellyseerrDownloadProvider.cs # Jellyseerr integration
│ ├── NativeDownloadProvider.cs # Direct Radarr/Sonarr integration
│ ├── WebhookDownloadProvider.cs # Custom webhook integration
│ └── DownloadProviderFactory.cs # Provider selection
├── VirtualLibrary/ # Virtual library system
│ ├── VirtualLibraryManager.cs # Stub file creation/management
│ ├── VirtualLibraryCreator.cs # Initialization
│ ├── VirtualLibraryContentType.cs # Enum of content types
│ └── VirtualLibraryContentTypeHelper.cs # Type mappings
├── Plugin.cs # Plugin entry point (singleton)
└── PluginServiceRegistrator.cs # Dependency injection setup
Key Design Patterns:
Provider System: Pluggable content sources via IContentProvider interface
Per-User Architecture: Each user has isolated configuration
Smart Caching: Multiple cache layers
Download Provider Pattern: Pluggable download backends
IDownloadProvider interface for extensibilityNativeDownloadProvider: Direct Radarr/Sonarr API callsJellyseerrDownloadProvider: Routes through Jellyseerr APIWebhookDownloadProvider: Custom HTTP webhook integrationPlayback Interception: Event-driven download triggers
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)git push origin feature/amazing-feature)Critical Implementation Details:
NamedClient.Default for Trakt API (avoids Cloudflare blocks)trakt-api-version: 2 and trakt-api-key headers (no User-Agent/Accept)extended=full on Trakt endpoints to get genre data for anime detectionUser entity (not Guid), use IUserManager.GetUserById()"Plugin not appearing after restart"
JellyNext_v1.0.0 (not just JellyNext)"Libraries showing as empty"
/jellyfin/data/jellynext-virtual/[user-id]/[content-type]/"Authorization stuck on 'Waiting...'"
"Token refresh failing"
"Cloudflare blocking requests"
NamedClient.Default"No recommendations appearing"
"Virtual libraries not updating"
"Too many API calls to Trakt"
"Downloads not triggering"
"Downloads trigger but fail"
[tmdbid-12345])"Anime not going to anime folder/profile"
"User not being imported to Jellyseerr"
"Item marked as watched after download attempt"
"Jellyfin library scans taking too long"
"High memory usage"
Enable Extra Logging:
Useful Log Locations:
Q: Do I need a Trakt VIP subscription? A: No, JellyNext works with free Trakt accounts.
Q: Will this download content automatically? A: By default, downloads are triggered only when you click "Play" on a virtual library item (one-click). However, you can enable Watchlist Sync to automatically add Trakt watchlisted items to your download system.
Q: Can I use this without Radarr/Sonarr/Jellyseerr? A: Yes, you can still use the virtual libraries to browse recommendations. Downloads just won't work.
Q: Which integration mode should I use? A:
Q: Do I need both Jellyseerr AND Radarr/Sonarr? A: If using Jellyseerr mode, you only need to configure Jellyseerr. Jellyseerr then communicates with Radarr/Sonarr. In Native mode, you configure Radarr/Sonarr directly. In Webhook mode, you configure your own custom endpoint.
Q: Can I integrate with systems other than Radarr/Sonarr? A: Yes! Use Webhook mode to integrate with any system that accepts HTTP requests. See the Webhook Integration Guide for examples.
Q: Does this affect my real Jellyfin libraries? A: No, virtual libraries are completely separate. They don't modify or interfere with your existing media.
Q: Can multiple users use this on the same Jellyfin server? A: Yes! Each user links their own Trakt account and gets their own virtual libraries with personalized recommendations.
Q: How often does it sync with Trakt? A: Default is every 6 hours. Configurable via "Cache Expiration (hours)" setting.
Q: What's the difference between Show Recommendations and Next Seasons? A:
Q: Why only 10 seasons for show recommendations? A: Performance. Jellyfin scans can be slow with thousands of stub files. Enable "Limit Shows to Season 1" for even better performance.
Q: How does anime detection work? A: Plugin checks if Trakt metadata includes "anime" genre, then routes to your configured anime root folder in Sonarr.
Q: Can I customize which recommendations appear? A: Yes, via per-user settings:
Q: How does Watchlist Sync work? A: When enabled, JellyNext checks your Trakt watchlist every hour and automatically adds new items to your configured download system (Radarr/Sonarr, Jellyseerr, or Webhook). Items already in your Jellyfin library or previously processed are skipped. Enable it per-user in the Trakt user settings.
Q: Does this use my Jellyfin API key? A: No, it uses Trakt's OAuth system. Each user authorizes the plugin via Trakt's website.
Q: Is this an official Jellyfin plugin? A: Not yet. It's currently community-maintained. Official repository submission planned for future.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Copyright (C) 2025 luall0
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
65 commits
C#
76.0%
HTML
12.2%
JavaScript
11.7%