mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
Co-authored-by: Alex Kim <alexkim@Alexs-MacBook-Pro.local> Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com> Co-authored-by: Simon-Eklundh <simon.eklundh@proton.me>
4.6 KiB
4.6 KiB
CLAUDE.md
@.claude/learned-facts.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Streamyfin is a cross-platform Jellyfin video streaming client built with Expo (React Native). It supports mobile (iOS/Android) and TV platforms, with features including offline downloads, Chromecast support, and Jellyseerr integration.
Development Commands
CRITICAL: Always use bun for package management. Never use npm, yarn, or npx.
# Setup
bun i && bun run submodule-reload
# Development builds
bun run prebuild # Mobile prebuild
bun run ios # Run iOS
bun run android # Run Android
# TV builds (suffix with :tv)
bun run prebuild:tv
bun run ios:tv
bun run android:tv
# Code quality
bun run typecheck # TypeScript check
bun run check # BiomeJS check
bun run lint # BiomeJS lint + fix
bun run format # BiomeJS format
bun run test # Run all checks (typecheck, lint, format, doctor)
# iOS-specific
bun run ios:install-metal-toolchain # Fix "missing Metal Toolchain" build errors
Tech Stack
- Runtime: Bun
- Framework: React Native (Expo SDK 54)
- Language: TypeScript (strict mode)
- State Management: Jotai (global state atoms) + React Query (server state)
- API: Jellyfin SDK (
@jellyfin/sdk) - Navigation: Expo Router (file-based)
- Linting/Formatting: BiomeJS
- Storage: react-native-mmkv
Architecture
File Structure
app/- Expo Router screens with file-based routingcomponents/- Reusable UI componentsproviders/- React Context providershooks/- Custom React hooksutils/- Utilities including Jotai atomsmodules/- Native modules (vlc-player, mpv-player, background-downloader)translations/- i18n translation files
Key Patterns
State Management:
- Global state uses Jotai atoms in
utils/atoms/ settingsAtominutils/atoms/settings.tsfor app settingsapiAtomanduserAtominproviders/JellyfinProvider.tsxfor auth state- Server state uses React Query with
@tanstack/react-query
Jellyfin API Access:
- Use
apiAtomfromJellyfinProviderfor authenticated API calls - Access user via
userAtom - Use Jellyfin SDK utilities from
@jellyfin/sdk/lib/utils/api
Navigation:
- File-based routing in
app/directory - Tab navigation:
(home),(search),(favorites),(libraries),(watchlists) - Shared routes use parenthesized groups like
(home,libraries,search,favorites,watchlists) - IMPORTANT: Always use
useAppRouterfrom@/hooks/useAppRouterinstead ofuseRouterfromexpo-router. This custom hook automatically handles offline mode state preservation across navigation:// ✅ Correct import useRouter from "@/hooks/useAppRouter"; const router = useRouter(); // ❌ Never use this import { useRouter } from "expo-router"; import { router } from "expo-router";
Offline Mode:
- Use
OfflineModeProviderfrom@/providers/OfflineModeProviderto wrap pages that support offline content - Use
useOfflineMode()hook to check if current context is offline - The
useAppRouterhook automatically injectsoffline=trueparam when navigating within an offline context
Providers (wrapping order in app/_layout.tsx):
- JotaiProvider
- QueryClientProvider
- JellyfinProvider (auth, API)
- NetworkStatusProvider
- PlaySettingsProvider
- WebSocketProvider
- DownloadProvider
- MusicPlayerProvider
Native Modules
Located in modules/:
vlc-player- VLC video player integrationmpv-player- MPV video player integration (iOS)background-downloader- Background download functionalitysf-player- Swift player module
Path Aliases
Use @/ prefix for imports (configured in tsconfig.json):
import { useSettings } from "@/utils/atoms/settings";
import { apiAtom } from "@/providers/JellyfinProvider";
Coding Standards
- Use TypeScript for all files (no .js)
- Use functional React components with hooks
- Use Jotai atoms for global state, React Query for server state
- Follow BiomeJS formatting rules (2-space indent, semicolons, LF line endings)
- Handle both mobile and TV navigation patterns
- Use existing atoms, hooks, and utilities before creating new ones
- Use Conventional Commits:
feat(scope):,fix(scope):,chore(scope):
Platform Considerations
- TV version uses
:tvsuffix for scripts - Platform checks:
Platform.isTV,Platform.OS === "android"or"ios" - Some features disabled on TV (e.g., notifications, Chromecast)