This commit is contained in:
2026-05-02 19:16:50 +03:00
parent 3443c29f66
commit 3803aca188
+139 -18
View File
@@ -1,32 +1,153 @@
# Jellybloom
A desktop media client for Jellyfin. Built with React, TypeScript, Vite, and Tauri.
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
## what it does
- Browse and play your Jellyfin library - movies, shows, music, live TV
- Discover new titles via TMDB integration with gap-finding against your library
- Watchlist sync with Trakt.tv
- Rich detail pages with cast, crew, awards, filming locations, and reviews
- Customizable player with subtitle search, bookmarks, chapter navigation, and audio passthrough
- Desktop-native feel via Tauri (Windows, macOS, Linux)
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.
## Dev
### 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
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
```
## Stack
## license
- React 19 + TypeScript
- Vite + Tailwind CSS
- Tauri 2
- Zustand for state
- TanStack Query for data fetching
- Vidstack + hls.js for playback
- libass-wasm for subtitle rendering
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.