readme
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user