# 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 ```bash 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.