A TV application built for browsing and playing content on Apple TV (tvOS) and Android TV. The app is fully remote-driven, allowing users to navigate between screens, select content, and play videos using standard TV remote controls (Up, Down, Left, Right, Enter, Back).
- Content Browsing: Horizontal carousels on the Home and Search screens to discover content.
- Watch Later & Liked Lists: Add or remove content from your personal lists. Persisted in storage and accessible via the Home and Profile screens.
- Watch History: Automatically saves the last 10 played items (without duplicates) when opening the player. Viewable on the Profile screen.
- Search: Virtualized grid with filtering capabilities by title or description.
- User Profiles: Choose from a list of preset avatars. Displays the selected avatar and name (falls back to "Unknown" if not set).
- Localization (EN / RU): Full support for English and Russian. Preferences are saved in storage. Defaults to the saved choice or device language on startup.
- Remote Control Support: Built-in focus management using LRUD (Left, Right, Up, Down) spatial navigation. Features an expandable sidebar menu on focus.
- Core: React 19, TypeScript
- Framework: Expo SDK 54 +
react-native-tvos(TV builds) - Navigation: React Navigation (Bottom tabs for the custom sidebar menu + Native stack)
- State Management: Zustand (search, avatar, watchlist, likedlist, history)
- Storage: AsyncStorage (persistence for lists, avatar, language)
- Localization: i18next / react-i18next
- Styling: Emotion (styled-components, theming)
- TV Navigation:
react-tv-space-navigation(focus and remote navigation) - Media & UI:
expo-video(video playback),react-native-fast-image(image caching for avatars and posters),lucide-react-native(icons)
The app uses AsyncStorage to persist user data locally. On app start, the following data is hydrated from storage directly into the Zustand store:
watchlistβ Items marked as "Watch later"likedlistβ Items marked as "Liked"historyβ Last 10 played items (stored by ID)avatarβ Selected user avatarlangβ Selected language (enorru)
The app is structured with a root Tab navigator (acting as a sidebar) and a Stack navigator on top for overlay screens.
The sidebar expands to show labels when focused.
| Screen | Description |
|---|---|
| Home | Hero section ("Expo Cinema TV") and horizontal carousels: Shorts Roku, Watch later, Liked content, Roku Series, Roku Movies. Combines mock data with personal lists. |
| Search | Search field with a virtualized result grid. Filters by title/description. Selecting a card opens the Interstitial screen. |
| Profile | Displays user avatar and name. Includes an "Edit" button to change the avatar. Features carousels for: History, Watch later, and Liked content. |
| Settings | Language switch (English / Russian). The choice is saved to storage and applied app-wide. |
| Screen | Description |
|---|---|
| Interstitial | Content details view: Poster, title, description, release date, genres. Actions include Like, Watch later, play (opens Player), and a "You may also like" section. |
| Player | Video playback screen using expo-video. Includes play/pause, progress, and volume controls. Opening this screen adds the item to the watch history. |
| EditAvatar | Horizontal avatar carousel allowing users to pick a preset avatar. The selection is saved to storage and navigates back to the Profile. |
src/
βββ config/ # Remote control configuration (configureRemoteControl)
βββ constants/ # Menu items, predefined avatars, mock content data
βββ context/ # React Contexts (LanguageProvider, MenuProvider)
βββ features/
β βββ video-player/ # Player UI, controls, watchlist/likedlist store, utils
β βββ store/
β βββ ui/
β βββ utils/
βββ i18n/ # i18next configuration, locales (en, ru)
β βββ locales/
βββ lib/
β βββ storage/ # AsyncStorage wrapper, storage keys schema
βββ navigation/ # React Navigation setup (RootStack, RootTab)
βββ providers/ # AppProvider (theme setup, hydration, i18n initialization)
βββ screens/ # Screen components (Home, Search, Profile, Settings, etc.)
βββ store/ # Zustand stores (search, avatar, historylist)
βββ styles/ # Emotion Theme (colors, typography, spacing, sizes), templates
βββ types/ # TypeScript definitions (TMovie, TAvatar, etc.)
βββ utils/ # Helper functions (scaledPixels, getDeviceLang, etc.)
βββ components/
β βββ navigation/ # Navigation UI (Menu, SpatialRow, GoBack)
β βββ screens/ # Screen-specific UI (ProfileImage, Interstitial elements, etc.)
β βββ shared/ # Reusable UI components (Typography, Buttons, Focusable components)
βββ hooks/ # Custom hooks (useLanguageContext, PanEvent / RemoteControl)
To run the application locally, use the following commands:
For Apple TV (tvOS):
# Choose a simulator from the list when prompted
npm run iosFor Android TV:
# Ensure an emulator/device is running and selected
npm run androidnpm run typecheckβ Run TypeScript compiler checks.npm run prebuildornpm run prebuild:tvβ Generate native prebuilds when native code changes are required.