A mobile-first custom video player inspired by the YouTube mobile experience, built with React 19, TypeScript, Motion, and Tailwind CSS.
StreamX focuses on smooth playback, gesture-driven UX, and high-performance rendering across mobile and desktop.
Live Demo: [Add your deployed URL]
- Category-grouped scrollable video feed
- Rich video cards (thumbnail, title, duration, category badge)
- Smooth list ↔ player transitions
- IntersectionObserver-based incremental loading
- Fully responsive grid (mobile → desktop)
- Auto-play on open
- Custom controls (Play/Pause, ±10s, seek bar, volume)
- Seekable progress bar with buffered indicator
- Current time / total duration
- Keyboard shortcuts support
- Fullscreen API support
- Mobile + desktop responsive behavior
Streaming support:
- MP4 via native
<video> - HLS via
hls.jsfallback
- Swipe/scroll to reveal related videos
- Auto-filtered by category
- Instant switch with autoplay
- Virtualized list for performance
- Smooth animated panel
- Drag down to minimize player
- Docked bottom mini-player
- Persistent playback while browsing
- Tap mini-player to restore
- Mini-player controls (Play/Pause, PiP, Maximize, Close)
- Auto-play next with 2s countdown + cancel
- Browser Picture-in-Picture (HTML5 video)
- Visual feedback for ±10s skips
- Hardware-accelerated 60fps animations
- First-use gesture hints (localStorage)
All core requirements from the assignment are implemented:
- ✅ Home Page - Video Feed
- ✅ Full-Page Video Player
- ✅ In-Player Video List
- ✅ Drag-to-Minimize Player
- ✅ HLS support (bonus)
- ✅ Virtualization / incremental loading (bonus)
- ✅ PiP support (HTML5 video)
These are platform constraints, not implementation gaps:
-
Buffered range parity
YouTube IFrame API does not expose native buffered ranges like<video>. -
Seek preview thumbnails
Not available for YouTube iframe playback. -
Browser PiP
requestPictureInPicture()is only supported for HTML5 video. -
Duration resolution
YouTube durations are fetched lazily and cached.
First render may briefly show cards without duration.
Feature-based modular structure:
src/
├── app/ # App shell, entry, global styles
├── pages/ # Route-level components
├── features/ # Feed + Player modules
└── shared/ # Types, utils, dataData flow philosophy:
- Player shell orchestrates state
- Feature modules remain isolated
- Shared layer is framework-agnostic
- React 19 + Vite 7
- TypeScript (strict)
- Tailwind CSS v4
- Motion v12
- hls.js
- clsx + tailwind-merge
npm install
npm run devnpm run build
npm run previewProduction output → dist/
| Device | Layout |
|---|---|
| Mobile | Single-column feed, touch gestures |
| Tablet | 2-column feed |
| Desktop | 3-column feed, hover enhancements |
| Key | Action |
|---|---|
| Space | Play / Pause |
| ← | Skip back 10s |
| → | Skip forward 10s |
MIT