A premium, cinematic Jellyfin client built with Expo & React Native β fast, private, offline-ready, and designed for a modern streaming experience.
Built with Expo SDK 57, React Native 0.86 (New Architecture & Hermes), and TypeScript.
π¬π§ English β’ π«π· FranΓ§ais
π₯ Browse APK Releases β’ π Quickstart β’ π€ Contributing β’ π¬ Discussions β’ π‘οΈ Security
- Overview
- FINORA in Action
- Highlights
- Download & Installation
- Detailed Features
- Tech Stack
- Project Architecture
- Getting Started
- Automated Testing & CI
- Security & Privacy
- Contributing
- Community & Support
- License & Acknowledgements
FINORA is an open-source personal media client focused on delivering a modern, cinematic mobile streaming experience for Jellyfin.
Built with Expo SDK 57, React Native 0.86, and TypeScript, it combines native hardware-accelerated playback, resilient background downloads, responsive navigation, and privacy-focused credential storage in a polished mobile interface.
The Core Experience:
Open FINORA β Browse instantly β Choose content β Play β Watch smoothly β Resume anywhere.
- Smooth Navigation: Optimized for high-refresh-rate displays (up to 120 Hz) using React Native's New Architecture (Fabric renderer and Hermes engine).
- Cinematic Dark Theme: Refined OLED dark theme, Netflix-style navigation, subtle elevation, and responsive cards.
- Native Video Engine: Built on modern
expo-video(AndroidX Media3 / ExoPlayer on Android and AVPlayer on iOS) with automated stream negotiation. - Privacy by Default: Authentication tokens stored in hardware-backed keystores where supported by the platform, passwords discarded immediately after authentication, and zero third-party telemetry.
| π Home | π¬ Details | π Search | π₯ Downloads | |
|---|---|---|---|---|
| Hero banners, continue watching & library carousels | Rich metadata, season picker & episode grids | Low-overhead playback, gestures & skip markers | Instant multi-library search with live filters | Background download manager with auto-resume |
- π¬ Native Jellyfin Playback β Low-overhead hardware decoding via AndroidX Media3 (ExoPlayer) & AVPlayer.
- π₯ Resilient Offline Downloads β Background media caching with HTTP Range resume after network drops or app restarts.
- π Secure Credential Storage β Access tokens use
expo-secure-storewhere available; passwords are never persisted and local references are discarded immediately after authentication. - π Fast Library Search β Instant multi-library search with live suggestions and per-user history isolation.
- ποΈ Intro & Credits Skipping β Dynamic skip markers based on Jellyfin chapter metadata.
- π Multi-Audio & Subtitles β Flexible track selection with custom subtitle overlay (SRT, WebVTT, ASS styling).
- π± Modern Responsive UI β Fluid dark interface optimized for portrait, landscape, and foldable form factors.
- π« Strict Privacy β No advertisements, third-party analytics, or telemetry.
Standalone APKs are built automatically on every release:
| Build Channel | Recommended For | Link |
|---|---|---|
| Release Candidates / Previews | Testers validating the upcoming stable release | Browse APK Releases |
| Stable | Use only after a stable vX.Y.Z release is published |
Browse All Releases |
- Download the
.apkfile directly on your Android phone from the GitHub Releases page. - Tap the downloaded file in your browser notifications or file manager.
- If prompted, allow your browser or file manager to "Install unknown apps".
- Tap Install and launch FINORA.
Due to platform restrictions on third-party streaming clients, running FINORA on iOS requires compiling from source:
- Clone the repository on a macOS machine with Xcode installed.
- Run
npx expo run:iosto compile and deploy to a connected iPhone or iOS simulator.
- AndroidX Media3 & AVPlayer: Native video decoding with hardware acceleration and low memory footprint.
- Stream Negotiation: Automated decision pipeline (
PlaybackPlanner) prioritizing Direct Play > Direct Stream > Transcoding based on device profile. - Intuitive Gesture Controls:
- Vertical swipe on the left edge for brightness control.
- Vertical swipe on the right edge for volume adjustment.
- Double-tap on the left/right edges for instant 10-second seek.
- Intro & Credits Skipping: Automatic skip marker detection for Jellyfin intros, recaps, and credits chapters.
- Subtitles & Multi-Audio: Support for SubRip (SRT), WebVTT, picture-based subtitles (PGS), and Advanced SubStation Alpha (ASS) styling via a dedicated subtitle overlay.
- Watch State Synchronization: Real-time playback progress reporting and resume points synced directly with your Jellyfin server.
- Hero Backdrop Banners: Dynamic backdrops, high-resolution logos, and auto-computed watch progress bars.
- Optimized Media Caching: Powered by
expo-imagewith multi-tier memory and disk caching, progressive JPEG/WebP decoding, and Blurhash placeholders. - Responsive Layout: Fluid grids and carousels adapting seamlessly between portrait, landscape, and foldable form factors.
- Background Downloads: Uses Android foreground services (
react-native-background-actions) to download large media files while the app is suspended. - Auto-Resume & Range Requests: Automatically resumes interrupted downloads after network drops or app restarts without restarting from byte zero.
- Isolated Sandboxing: Offline media files and metadata are stored in private app sandbox storage (
expo-file-system) and indexed locally per server and per user.
- Live Search: Rapid search with real-time suggestions, recent search history, and multi-library results.
- Multi-Server & User Isolation: Search histories, download indexes, and view preferences are fully isolated per server and per user.
- Rich Metadata Display: Detailed cast lists, community ratings, studio badges, and media resolution tags (4K, HDR, 1080p, 5.1 Surround).
- Platform Secure Storage: Authentication tokens are stored through
expo-secure-store; hardware-backed properties depend on the device and operating system. - Credential Lifetime: Passwords are never persisted and FINORA discards its local password reference immediately after authentication completes.
- Sanitized Logging: All network logs and debugging outputs automatically redact authorization headers, passwords, and tokens (
[REDACTED]). - Zero Third-Party Trackers: No analytics, telemetry, or third-party ads.
- Periodic background fetch (
expo-background-task) checks for newly released movies, seasons, and episodes on your Jellyfin server.
| Layer | Technologies | Purpose |
|---|---|---|
| Framework | Expo SDK 57 | Managed native build plugins, modern runtime modules |
| Runtime | React Native 0.86+ + React 19 | Native UI components, modern concurrent rendering |
| Architecture | New Architecture (Fabric + Bridgeless) | Direct native synchronous invocation via JSI, removing legacy bridge overhead |
| JS Engine | Hermes | Fast startup time and lightweight memory footprint via bytecode precompilation |
| Routing | Expo Router v4 | Typed file-based routing with native transitions |
| Player | expo-video |
AndroidX Media3 / ExoPlayer on Android & AVPlayer on iOS |
| Images | expo-image |
Native disk/memory caching with blurhash support |
| State | TanStack Query v5 + Zustand | Server state caching & lightweight atomic UI stores |
| Security | expo-secure-store |
Platform secure storage for Jellyfin access tokens; hardware-backed properties depend on device/OS |
| SDK | @jellyfin/sdk |
Official typed Jellyfin API client |
| Language | TypeScript | Strict mode type-safety across the entire codebase |
FINORA enforces a strict separation of concerns to keep business logic maintainable, testable, and isolated:
FINORA Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Expo Router Pages β (src/app/)
β Screen Presentation & Reanimated Transitions β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Custom Hooks β (src/features/*/hooks/)
β UI Lifecycle, Gesture Arbitrators, Queries β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Domain & State Layer (TanStack/Zustand) β (src/stores/, src/features/)
β PlaybackPlanner, DownloadManager, OfflineEngine β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Repository Layer β (src/core/repositories/)
β AuthRepo, MediaRepo, PlaybackRepo, SessionRepo β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββββ
β Native Modules & Jellyfin Engine β (expo-video, SecureStore, SDK)
β AndroidX Media3, Keystore, @jellyfin/sdk β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FINORA/
βββ assets/ # Branding assets, logos, and icons
βββ docs/ # Documentation & release checklists
βββ src/
β βββ app/ # Expo Router typed file-based navigation
β β βββ (tabs)/ # Main tab navigation (Home, Search, Downloads, Settings)
β β βββ details/ # Media and series details view
β β βββ player/ # Fullscreen video player route
β βββ core/ # Foundational infrastructure
β β βββ jellyfin/ # Auth repository, SDK clients, and restore logic
β β βββ network/ # Sanitized HTTP client, logger, and network status
β β βββ repositories/ # Media, playback, user, and user-data repositories
β β βββ security/ # Keystore encryption, sanitization, and token storage
β β βββ storage/ # Secure store & preferences handlers
β βββ features/ # Feature modules
β β βββ details/ # Media details, season picker, episode cards
β β βββ home/ # Hero banner, media carousels, resume watching
β β βββ library/ # Responsive media grid, filters, sorting
β β βββ notifications/# Background notifications for new server content
β β βββ offline/ # DownloadManager, background worker, resume logic
β β βββ onboarding/ # Server discovery and authentication
β β βββ player/ # FinoraPlayerEngine, controls, gestures, subtitles
β β βββ search/ # Live search, history, suggestions
β β βββ settings/ # Server diagnostics, playback & subtitle preferences
β βββ stores/ # Atomic Zustand stores (player, settings, downloads)
β βββ components/ # Design system components, FinoraCard, modals
βββ .github/ # Issue templates, PR template, CI workflows
βββ package.json
β οΈ FINORA requires an Expo development build β it cannot run in Expo Go.
Native modules used by FINORA (expo-video,expo-secure-store,expo-background-task, etc.) require native code compilation.
- Node.js v22+ (LTS recommended)
- npm v10+
- JDK 17 (Temurin 17 recommended)
- Android Studio with Android SDK Platform 35+ and Android NDK
- A running Jellyfin Media Server
-
Clone the repository:
git clone https://github.com/MEHDImp4/FINORA.git cd FINORA -
Install dependencies:
npm install
-
Run on Android (generates native project and launches dev build):
npx expo run:android
-
Run on iOS (macOS required):
npx expo run:ios
-
Start the Metro development server:
npx expo start --dev-client
| Command | Action |
|---|---|
npm start |
Start Metro development bundler |
npm test |
Run the complete automated Jest test suite |
npm run typecheck |
Run TypeScript compiler in strict mode without emitting files |
npm run android |
Compile and launch native Android development build |
npm run ios |
Compile and launch native iOS development build |
FINORA maintains an automated test suite covering repository caching, playback planning, download recovery, and state managers:
# Run unit & integration tests
npm test
# Run TypeScript strict validation
npm run typecheckContinuous Integration runs on every push and pull request to master via GitHub Actions:
- TypeScript Strict Validation
- Jest Unit & Integration Test Execution
- Version and i18n consistency checks
- Production Dependency Security Audit (
npm audit --omit=dev --audit-level=high) - Expo Doctor (advisory)
- Automated Standalone APK Packaging via GitHub Actions (
build-apk.yml)
- Credential Handling: Passwords are never persisted; local references are discarded immediately after authentication and sensitive values are redacted from logs.
- Hardware-Encrypted Keystore: Access tokens are stored in hardware-backed storage (
expo-secure-store) where available on device. - Sanitized Logging: All network logs and debugging outputs automatically redact authentication headers, tokens, and query credentials (
[REDACTED]). - No Third-Party Trackers: Zero telemetry, zero analytics, zero external user tracking.
- Responsible Disclosure: Please see our Security Policy to report vulnerabilities privately.
We welcome contributions of all kinds from the community!
- π Found a bug? Open a Bug Report or Playback Issue.
- π‘ Have an idea? Submit a Feature Request.
- π» Want to write code? Read our Contributing Guide and check our Code of Conduct.
- GitHub Discussions: Share setup tips, show off your server configuration, or discuss feature ideas in Discussions.
- Issue Tracker: Track ongoing fixes and feature developments in Issues.
- Feature Requests: Propose enhancements and discuss ideas via Feature Requests.
- Releases: Download standalone builds and review changelogs in Releases.
FINORA is free software, licensed under the GNU General Public License v3.0 (GPL-3.0). See LICENSE for details.
- The awesome Jellyfin project and community for creating the open-source media system.
- The Expo and React Native teams for the modern mobile development platform.
