Jellybloom
A desktop media client for Jellyfin that actually feels good to use.
Built for people who run their own servers. No cloud, no accounts, no subscriptions, no gatekeepers between you and your library.
🏴 Why Jellybloom?
You already run a Jellyfin server. You already own the media. So why does using it still feel like using a web app designed by committee?
Jellybloom is a ground-up desktop client for Windows. It talks directly to your Jellyfin server and makes browsing, discovering, and watching actually pleasant. Fast, dense, responsive, and fully under your control.
No cloud dependencies. No data collection. No feature gates. No one profits from your watch history except you.
✨ What it does
📺 Browse
- Home shelves - curate your own rows or let the app suggest based on what you watch
- Virtualized poster grid - smooth scrolling with thousands of items
- Unified fuzzy search - titles, people, collections. Saved searches stick around
- Quick look - right-click any poster for a peek without losing your scroll position
- Notification bell - new episodes and movies, deduplicated by series so a full-season drop does not flood you
🎬 The player
- Native subtitle rendering - ASS/SSA via libass-wasm, plus SRT, VTT, and plain text
- Subtitle search - find and download from OpenSubtitles without leaving the player
- Subtitle styling - size, font, outline, color, background opacity, positioning
- Bookmarks - drop a pin with a note, shown as dots on the scrubber
- A-B loop - for study, reference, or that one perfect joke
- Chapters and trickplay thumbnails - jump around, hover the scrubber to see where you are
- Speed control - 0.5x to 3x
- Picture filter - brightness, contrast, saturation, hue, gamma for bad encodes
- Audio graph - compressor and parametric EQ for quiet or loud mixes
- Audio passthrough - let your receiver handle decoding
- Quality and track menus - switch streams on the fly
- Resume prompt - asks first so you do not spoil the cold open
- End card - next episode or related title as the credits roll
- Mini player - pop out to a floating window
- Sleep timer - fades out after your chosen duration
- "Still watching?" - gently checks in after a few episodes
- Downloads - save for offline playback
- Cast - send to another Jellyfin session on your network
- SyncPlay - watch together with friends, playback stays locked
- Trakt.tv scrobbling - optional, device-code auth, no redirects
- Customizable keyboard shortcuts - rebind everything
📄 Detail pages
- Hero - backdrop, poster, logo overlay, ratings, action buttons
- Cast and crew - clickable filmographies with in-library matches highlighted
- Composer block - because the score matters
- Awards - from Wikidata
- Filming locations - mapped with Leaflet
- Reception - aggregates IMDb, TMDB, Rotten Tomatoes, Metacritic, and your own ratings
- Reviews, trailers, trivia, tech specs - from TMDB, YouTube, Wikipedia
- Collection strip - franchise entries
- Series status - air days, next episode, season count, production state
- Anime filler detection - flags filler and mixed-canon episodes
- Versions selector - pick between multiple files for one title
- Watch timeline - your personal history from the diary
- Personal section - your ratings, rewatch counts, notes. Stays local
- Diary - log watches with date, rating, rewatch flag. Export to Markdown, JSON, or Letterboxd CSV
- Request button - ask Radarr or Sonarr for missing titles without leaving the page
🔭 Discover
Find things you do not already own. Needs a free TMDB API key.
- Tonight hero - personalized spotlight based on your top genre
- Spotlight hero - trending pick of the day
- Mood chips - ten vibes that resolve to a filtered row
- Roulette - spin for a random highly-rated title
- Decade strips - the 90s, the 80s, etc.
- Canonical lists - top rated, cult classics, upcoming
- On this day - titles that premiered today
- Library gap finder - highest-rated missing titles in genres you already watch
- Browse grid - by genre, language, studio, network. Inline expansion
- Advanced filters - year range, rating, vote count, sort order
👤 Profile and stats
- Watch streak, genre breakdown, year-in-review
- Personally top-rated titles, recent diary entries
⚙️ Settings
- Multiple Jellyfin servers with live dashboard
- Playback, audio, subtitle, and display preferences
- Home page and detail page section toggles
- TMDB, Fanart.tv, Trakt.tv, Sonarr, Radarr configuration
- Personal data management, privacy controls, full keyboard rebinds
♿ Accessibility
Jellybloom targets WCAG 2.2 AAA conformance because a media client that only works for some people is not really a media client.
| Area | Details |
|---|---|
| Semantic HTML | Proper landmarks, ARIA roles for menus, dialogs, tabs, and status regions |
| Full keyboard navigation | Every interactive element reachable and operable without a mouse |
| Focus management | Visible focus indicators on all controls, focus traps in modals with restore on close |
| High contrast | All themes meet AAA contrast ratios (7:1+ for normal text) |
| Reduced motion | Respects prefers-reduced-motion - all animations disabled when active |
| Screen readers | ARIA live regions for dynamic content, proper labels on icon-only buttons |
| Touch targets | All interactive controls meet 24x24px minimum |
📦 Getting started
Prerequisites
- Windows 10 or later
- WebView2 Runtime (pre-installed on Windows 10/11)
- Node.js 18+
- Rust (latest stable)
- Tauri v2 prerequisites
Development
git clone https://git.lashman.live/lashman/jellybloom.git
cd jellybloom
npm install
npm run dev # browser dev
npm run tauri:dev # desktop dev
npm run build # production web build
npm run tauri:build # production desktop build
🔧 Technology stack
| Layer | Technology | |
|---|---|---|
| Runtime | Desktop shell | Tauri v2 |
| Frontend | UI framework | React 19, TypeScript, Vite |
| Styling | CSS | Tailwind CSS 4 |
| State | Management | Zustand |
| Data | Fetching and caching | TanStack Query |
| Lists | Virtualization | TanStack Virtual |
| Playback | Media engine | Vidstack, hls.js |
| Subtitles | Rendering | libass-wasm |
| Animation | Transitions | Framer Motion |
| Maps | Locations | Leaflet |
| Search | Fuzzy matching | Fuse.js |
| Primitives | Accessibility | Radix UI |
🗂️ Project structure
jellybloom/
├── src/
│ ├── api/ API clients (Jellyfin, TMDB, Fanart, etc.)
│ ├── components/ UI components (player, detail, discover, layout)
│ ├── hooks/ Data hooks and player logic
│ ├── lib/ Utilities, formatters, device profile
│ ├── pages/ Route pages
│ ├── stores/ Zustand stores
│ └── types/ TypeScript declarations
├── src-tauri/ Rust backend
│ ├── src/
│ ├── capabilities/
│ └── icons/
├── public/ Static assets
├── package.json
├── vite.config.ts
└── tsconfig.json
📜 License
Dedicated to the public domain under CC0 1.0 Universal.
No copyright, no restrictions, no permission needed. Take it, use it, change it, share it. The culture belongs to everyone.