150 lines
8.0 KiB
Markdown
150 lines
8.0 KiB
Markdown
<div align="center">
|
|
|
|
# Jellybloom
|
|
|
|
**A desktop media client for Jellyfin that actually feels good to use.**
|
|
|
|
Built for people who run their own servers. No cloud, no accounts, no subscriptions, no gatekeepers between you and your library.
|
|
|
|
<br>
|
|
|
|
<img src="https://img.shields.io/badge/version-0.1.0-6B8AFF?style=flat-square&labelColor=282C33" alt="Version">
|
|
<img src="https://img.shields.io/badge/platform-Windows-6B8AFF?style=flat-square&labelColor=282C33" alt="Platform">
|
|
<img src="https://img.shields.io/badge/React-19-61DAFB?style=flat-square&logo=react&logoColor=white" alt="React">
|
|
<img src="https://img.shields.io/badge/Tauri-v2-24C8D8?style=flat-square&logo=tauri&logoColor=white" alt="Tauri">
|
|
<img src="https://img.shields.io/badge/license-CC0_Public_Domain-6B8AFF?style=flat-square&labelColor=282C33" alt="License">
|
|
|
|
</div>
|
|
|
|
<br>
|
|
|
|
## 🏴 Why Jellybloom?
|
|
|
|
You already run a Jellyfin server. You already own the media. So why does using it still feel like using a web app designed by committee?
|
|
|
|
Jellybloom is a ground-up desktop client for Windows. It talks directly to your Jellyfin server and makes browsing, discovering, and watching actually pleasant. Fast, dense, responsive, and fully under your control. No cloud dependencies. No data collection. No feature gates. No one profits from your watch history except you.
|
|
|
|
<br>
|
|
|
|
## 🎬 What it does
|
|
|
|
### 📺 Browse
|
|
|
|
The home page is built from shelves you curate yourself, or you can let the app suggest rows based on what you actually watch. The poster grid uses virtualized scrolling so it stays smooth even with thousands of items. Right-click any poster for a quick look without losing your place. A notification bell tracks new episodes and movies, deduplicated by series so a full-season drop does not flood you. Search is fuzzy and unified across titles, people, and collections, and saved searches stick around if you find yourself looking for the same things repeatedly.
|
|
|
|
### 🎬 The player
|
|
|
|
This is where most of the work went. The player is built on Vidstack with hls.js, and the entire chrome layer is custom. ASS and SSA subtitles render natively through libass-wasm so styled fansubs look exactly as intended, with SRT, WebVTT, and plain text supported too. You can search OpenSubtitles from inside the player, tweak size, font, outline, color, background opacity, and positioning. A picture filter adjusts brightness, contrast, saturation, hue, and gamma for badly-encoded sources. An audio graph gives you a compressor and parametric EQ. Audio passthrough lets your receiver handle decoding when it can.
|
|
|
|
Beyond the basics: bookmarks with notes shown as dots on the scrubber, A-B looping, chapter navigation, trickplay thumbnails, speed control from 0.5x to 3x, a sleep timer, and a "still watching?" prompt that checks in after a few episodes so your stats do not run away. The resume prompt asks first so you do not spoil a cold open. The end card shows what is next as the credits roll. Pop out a mini player to keep watching while doing other things. Cast to another Jellyfin session on your network, or join a SyncPlay group to watch together with friends. Trakt.tv scrobbling is optional and uses device-code auth, no redirects. Every keyboard action can be rebound.
|
|
|
|
### 📄 Detail pages
|
|
|
|
Every title gets a rich detail page that pulls from multiple sources. The hero shows a backdrop, poster, and logo overlay from Jellyfin or TMDB, plus ratings and action buttons. Cast and crew are clickable, with in-library matches highlighted in a person's filmography. Awards come from Wikidata. Filming locations are mapped with Leaflet. Reception aggregates IMDb, TMDB, Rotten Tomatoes, Metacritic, and your own ratings. Reviews, trailers, trivia, and tech specs round it out, with badge icons for Dolby Vision, Atmos, DTS:X, and others. Anime filler detection flags filler and mixed-canon episodes. If you have multiple versions of a file, a selector lets you pick. The watch timeline draws from your diary. Your ratings, rewatch counts, and notes stay local. The diary lets you log watches and export to Markdown, JSON, or Letterboxd CSV. If something is missing, you can request it from Radarr or Sonarr without leaving the page.
|
|
|
|
### 🔭 Discover
|
|
|
|
Find things you do not already own. Needs a free TMDB API key. There is a personalized spotlight based on your top genre, a trending pick, mood chips that resolve to filtered rows, a roulette for random highly-rated titles, decade strips, canonical lists, an "on this day" feature, and a library gap finder that shows the highest-rated missing titles in genres you already watch. Browse by genre, language, studio, or network, with inline expansion and advanced filters for year range, rating, vote count, and sort order.
|
|
|
|
### 👤 Profile and stats
|
|
|
|
Track your watch streak, genre breakdown, year-in-review summary, personally top-rated titles, and recent diary entries.
|
|
|
|
### ⚙️ Settings
|
|
|
|
Connect to multiple Jellyfin servers with a live dashboard. Configure playback, audio, subtitle, and display preferences. Toggle home page rows and detail page sections. Set up TMDB, Fanart.tv, Trakt.tv, Sonarr, and Radarr. Manage personal data, privacy controls, and rebind every keyboard shortcut.
|
|
|
|
<br>
|
|
|
|
## ♿ Accessibility
|
|
|
|
Jellybloom targets WCAG 2.2 AAA conformance because a media client that only works for some people is not really a media client.
|
|
|
|
| Area | Details |
|
|
|:-----|:--------|
|
|
| **Semantic HTML** | Proper landmarks, ARIA roles for menus, dialogs, tabs, and status regions |
|
|
| **Full keyboard navigation** | Every interactive element reachable and operable without a mouse |
|
|
| **Focus management** | Visible focus indicators on all controls, focus traps in modals with restore on close |
|
|
| **High contrast** | All themes meet AAA contrast ratios (7:1+ for normal text) |
|
|
| **Reduced motion** | Respects prefers-reduced-motion - all animations disabled when active |
|
|
| **Screen readers** | ARIA live regions for dynamic content, proper labels on icon-only buttons |
|
|
| **Touch targets** | All interactive controls meet 24x24px minimum |
|
|
|
|
<br>
|
|
|
|
## 📦 Getting started
|
|
|
|
### Prerequisites
|
|
|
|
- Windows 10 or later
|
|
- WebView2 Runtime (pre-installed on Windows 10/11)
|
|
- Node.js 18+
|
|
- Rust (latest stable)
|
|
- Tauri v2 prerequisites
|
|
|
|
### Development
|
|
|
|
```bash
|
|
git clone https://git.lashman.live/lashman/jellybloom.git
|
|
cd jellybloom
|
|
npm install
|
|
```
|
|
|
|
```bash
|
|
npm run dev # browser dev
|
|
npm run tauri:dev # desktop dev
|
|
npm run build # production web build
|
|
npm run tauri:build # production desktop build
|
|
```
|
|
|
|
<br>
|
|
|
|
## 🔧 Technology stack
|
|
|
|
| | Layer | Technology |
|
|
|:--|:--|:--|
|
|
| **Runtime** | Desktop shell | [Tauri v2](https://tauri.app/) |
|
|
| **Frontend** | UI framework | React 19, TypeScript, Vite |
|
|
| **Styling** | CSS | Tailwind CSS 4 |
|
|
| **State** | Management | Zustand |
|
|
| **Data** | Fetching and caching | TanStack Query |
|
|
| **Lists** | Virtualization | TanStack Virtual |
|
|
| **Playback** | Media engine | Vidstack, hls.js |
|
|
| **Subtitles** | Rendering | libass-wasm |
|
|
| **Animation** | Transitions | Framer Motion |
|
|
| **Maps** | Locations | Leaflet |
|
|
| **Search** | Fuzzy matching | Fuse.js |
|
|
| **Primitives** | Accessibility | Radix UI |
|
|
|
|
<br>
|
|
|
|
## 🗂️ Project structure
|
|
|
|
```
|
|
jellybloom/
|
|
├── src/
|
|
│ ├── api/ API clients (Jellyfin, TMDB, Fanart, etc.)
|
|
│ ├── components/ UI components (player, detail, discover, layout)
|
|
│ ├── hooks/ Data hooks and player logic
|
|
│ ├── lib/ Utilities, formatters, device profile
|
|
│ ├── pages/ Route pages
|
|
│ ├── stores/ Zustand stores
|
|
│ └── types/ TypeScript declarations
|
|
├── src-tauri/ Rust backend
|
|
│ ├── src/
|
|
│ ├── capabilities/
|
|
│ └── icons/
|
|
├── public/ Static assets
|
|
├── package.json
|
|
├── vite.config.ts
|
|
└── tsconfig.json
|
|
```
|
|
|
|
<br>
|
|
|
|
## 📜 License
|
|
|
|
Dedicated to the public domain under [CC0 1.0 Universal](LICENSE).
|
|
|
|
No copyright, no restrictions, no permission needed. Take it, use it, change it, share it. The culture belongs to everyone.
|