9.0 KiB
Jellybloom
a desktop media client for Jellyfin, built because nobody should have to rent back their own culture from a server they already run
what it does
Jellybloom is a React + TypeScript + Vite + Tauri app that talks to your Jellyfin server and makes browsing, discovering, and watching actually pleasant. it is not a fork of jellyfin-web. it is not a skin. it is a complete reimagining of how a personal media library should feel - fast, dense, and yours.
browse
- movies, shows, music, playlists, live TV - the usual stuff, but with a poster-grid that doesn't make your scroll wheel cry
- unified search - fuzzy matching across titles, people, and collections. saved searches stick around if you want them to
- smart shelves - curate your own rows on the home page (or let the app suggest some based on what you actually watch)
- notification bell - new episodes and movies land here, deduplicated by series so a full-season drop doesn't flood you
- quick look - right-click any poster for a peek without losing your scroll position
player
the player is where most of the love went. it is built on Vidstack + hls.js with a custom chrome layer:
- subtitle rendering - native ASS/SSA via libass-wasm, so styled fansubs look exactly like they're supposed to. also supports SRT, VTT, and plain text
- subtitle search - search and download from OpenSubtitles without leaving the player
- subtitle styling - size, font, outline, color, background opacity, positioning
- bookmarks - drop a pin at any moment with a note. bookmarks show up as dots on the scrubber
- A-B loop - loop a section for study, reference, or that one perfect joke
- chapters - jump between chapters from the scrubber or a side panel
- trickplay thumbnails - hover the scrubber to see exactly where you are
- speed control - 0.5x to 3x, because some shows deserve it and others really don't
- picture filter - brightness, contrast, saturation, hue, and gamma. useful for badly-encoded sources
- audio graph - a lightweight compressor + parametric EQ chain for when the mix is too quiet or too loud
- audio passthrough - let your receiver handle decoding when it can
- quality menu - switch streams on the fly (or let the server decide)
- track menus - pick audio and subtitle streams without leaving fullscreen
- resume prompt - picks up where you left off, but asks first so you don't spoil the cold open
- up next / end card - shows the next episode or related title as the credits roll
- mini player - pop out to a small floating window and keep watching while you do other things
- sleep timer - fades out after your chosen duration so you don't wake up three seasons later
- "still watching?" prompt - gently checks if you're still there after a few episodes (prevents runaway binge stats)
- downloads - save a movie or episode for offline playback. stored as a blob URL in the session
- cast - send playback to another Jellyfin session on your network
- SyncPlay - watch together with friends. join or create a group, and playback stays locked
- Trakt.tv scrobbling - optionally logs what you watch to Trakt (device-code auth, no redirect nonsense)
- keyboard shortcuts - fully customizable. every action in the player and app can be bound to whatever key combo you want
detail pages
every title gets a rich detail page that pulls from multiple sources:
- hero - backdrop, poster, logo overlay (from Jellyfin or TMDB), rating badges, action buttons
- cast & crew - click any person for their filmography, with in-library matches highlighted
- crew grid - directors, writers, producers, with job labels
- composer block - because the score matters and nobody else puts it front and center
- awards - pulled from Wikidata. Oscars, BAFTAs, Golden Globes, and more
- filming locations - mapped with Leaflet. see where it was shot
- where to watch - streaming availability by region, via TMDB
- reception - aggregate of every rating source available (IMDb, TMDB, Rotten Tomatoes, Metacritic, your own)
- reviews - pulled from TMDB
- videos - trailers and clips from YouTube
- trivia - production notes and keywords from Wikipedia
- tech specs - codec, container, resolution, audio channels, HDR format. media tech badge icons for Dolby Vision, Atmos, DTS:X, etc.
- collection strip - franchise entries with the current title highlighted
- series status - air days, next episode, season count, whether it's still in production
- episode extras - guest stars, production codes, absolute numbering
- anime filler detection - flags filler and mixed canon episodes based on a bundled dataset
- versions selector - when you have multiple files for one title, pick the one you want
- watch timeline - your personal history with this title, drawn from the diary
- personal section - your own rating, rewatch count, and notes. this data stays local
- diary - log watches with a date, rating, and rewatch flag. export to Markdown, JSON, or Letterboxd CSV
- request button - if you don't have it, request it from Radarr or Sonarr without leaving the page
discover
the Discover page is for finding things you don't already own. it needs a TMDB API key (free) and respects your region and adult-content preference:
- tonight hero - a personalized spotlight based on your top genre
- spotlight hero - trending pick of the day
- mood chips - ten vibes ("cosy," "chaotic," "melancholic") that resolve to a filtered row
- roulette - spin for a random highly-rated title from your chosen kind
- decade strips - "the 90s," "the 80s," etc. with interleaved movie and TV picks
- canonical lists - "top rated," "cult classics," "upcoming"
- on this day - titles that premiered on today's date
- library gap finder - shows the highest-rated missing titles in genres you already watch
- browse grid - explore by genre, language, studio, or network. each tile expands inline
- advanced filters - year range, rating, vote count, genre, watch region, sort order
profile & stats
- watch streak - consecutive days with logged play activity
- genre breakdown - pie chart of what you actually watch
- year in review - hours watched, top genres, longest binge
- top rated - your personally highest-rated titles
- recent diary - last few logged watches
settings
a lot of care went into making everything configurable without drowning you in toggles:
- server - connect to one or many Jellyfin servers. switch between them without re-logging
- server dashboard - live stats: version, uptime, active streams, who's transcoding
- playback - autoplay, resume threshold, default audio language, subtitle language, subtitle size
- audio & subtitles - default behaviors, search preferences, styling defaults
- display - density (compact / comfortable), accent color, UI scale, reduced motion
- home page - toggle rows, pin smart shelves, hide adult content
- detail page - turn on/off sections you don't care about (trivia, filming locations, awards, etc.)
- episodes - default sort order, show/hide filler chips, absolute numbering
- discovery - region, hide adult, default filters
- TMDB - your own API key (optional built-in fallback)
- Fanart.tv - API key for richer artwork
- Trakt.tv - connect, sync watchlist, enable scrobbling
- Sonarr & Radarr - connect multiple instances (default + 4K tiers), set override rules per request
- personal - manage your ratings, rewatch counts, and diary
- privacy - clear caches, export data, delete everything
- shortcuts - rebind every keyboard action
- about - version, stack, acknowledgements
the little things
- sidebar pinning - pin it open or let it auto-hide
- window controls - minimize, maximize, close. the whole app is a drag region except the buttons
- offline banner - gentle notice when the server is unreachable
- toast system - non-intrusive feedback for actions
- error boundary - catches crashes and shows a recoverable screen instead of a white page
- reduced motion - respects the system preference
- density modes - compact for power users, comfortable for everyone else
stack
- React 19 + TypeScript
- Vite + Tailwind CSS
- Tauri 2 - desktop shell (Windows, macOS, Linux)
- Zustand - state management
- TanStack Query - data fetching and caching
- TanStack Virtual - virtualized lists
- Vidstack + hls.js - media playback
- libass-wasm - subtitle rendering
- Framer Motion - transitions and gestures
- Leaflet - maps
- Fuse.js - fuzzy search
- Radix UI - accessible primitives
dev
npm install
npm run dev # browser dev server
npm run tauri:dev # desktop dev
npm run build # production web build
npm run tauri:build # production desktop build
license
CC0 - this code is a common resource. take it, modify it, run your own fork, or don't. no attribution required, no permission needed. the culture belongs to everyone.