154 lines
9.0 KiB
Markdown
154 lines
9.0 KiB
Markdown
# 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.
|