The Question
FE DesignDesign a High-Performance Video Streaming Web Application
Design the frontend architecture for a global video streaming platform like YouTube. Your solution must address high-performance video playback using adaptive bitrate streaming, efficient rendering of infinite video feeds with thousands of items, and maintaining a continuous playback experience (mini-player) across client-side route transitions. Detail your approach to state management for the player, optimization techniques for Core Web Vitals, and how you would handle complex UI interactions like custom video controls and keyboard accessibility.
React
HLS.js
TanStack Query
Zustand
Tailwind CSS
Next.js
Web Session API
Intersection Observer
Questions & Insights
Clarifying Questions
Q: Which platforms are we prioritizing for the MVP?
Assumption: We are targeting modern Web browsers (Desktop and Mobile Web) to ensure maximum reach with a single codebase.
Q: What is the primary video delivery format and streaming protocol?
Assumption: We will use HLS (HTTP Live Streaming) or DASH to support Adaptive Bitrate Streaming (ABR) for various network conditions.
Q: Does the MVP require Digital Rights Management (DRM)?
Assumption: No. For the MVP, we will use signed URLs and token-based authentication to protect content, keeping complexity low.
Q: What are the core user journeys for the MVP?
Assumption: Browsing a video feed (Home), searching for content, and high-performance video playback. Social features like comments and likes are secondary.
Q: How much data are we dealing with for the initial feed?
Assumption: Thousands of videos. We need efficient list rendering (virtualization) and metadata fetching.
Crash Strategy
The core bottleneck in a video platform is perceived performance (the time between clicking a video and seeing the first frame) and scrolling efficiency (the "infinite scroll" jank).
How do we handle high-performance playback? Integrate a specialized Media Engine (HLS.js/Shaka) to manage buffer segments and quality switching outside the React render cycle.
How do we ensure a smooth browsing experience? Implement Windowing/Virtualization for the video feed to keep the DOM node count constant regardless of list size.
How do we optimize data fetching? Utilize a stale-while-revalidate strategy with prefetching for video metadata as the user hovers or scrolls.
How do we manage global player state? Centralize the "Mini-player" vs. "Full-screen" state in the application layer to allow continuous playback while navigating the site.
Elite Bonus Points
Media Session API: Integrate with OS-level media controls (lock screen, hardware media keys) for a native feel.
Predictive Prefetching: Use a small worker to pre-warm the TCP connection or pre-download the first
.ts segment of the most likely next video.Intersection Observer for Auto-play: Implement low-power silent previews for videos in the viewport to increase engagement without taxing the CPU.
Lighthouse/Web Vitals for Video: Track "Time to First Frame" (TTFF) and "Re-buffer Ratio" as custom user-centric metrics.
Design Breakdown
Requirements
Functional Requirements:
Video Feed (Infinite Scroll).
Search functionality.
Video Player with controls (Play/Pause, Seek, Volume, Quality Selector, Fullscreen).
Video Detail page with related videos.
Non-Functional Requirements:
Performance: Video start time < 2s; smooth 60fps scrolling.
Responsiveness: Support mobile, tablet, and desktop layouts.
Accessibility: ARIA labels for custom player controls; keyboard shortcuts (e.g., 'K' for pause).
Scalability: Handle thousands of video thumbnails without memory leaks.
Design Summary
Concise Summary: A modular SPA architecture focusing on a decoupled Media Engine and a virtualized presentation layer to ensure smooth discovery and playback.
Major Components:
VideoPlayerCore: A framework-agnostic wrapper around HLS.js/Shaka Player to handle the underlying
<video> element.VirtualizedFeed: A high-performance list component that renders only the visible thumbnails.
GlobalPlayerManager: A state container managing the lifecycle of the active video stream across routes.
SearchService: A throttled, cached interface for video discovery.
CUJ Walkthrough:
Browse: User scrolls
VirtualizedFeed; IntersectionObserver triggers metadata prefetching.Watch: User clicks a video;
GlobalPlayerManager initializes VideoPlayerCore, mounts it in the VideoPage, and starts HLS segment fetching.Navigate: User goes back to Home; the video continues in a "Mini-player" (PIP) mode via the
AppShell.Simplicity Audit: This design avoids complex DRM and heavy Micro-frontend architectures in favor of a clean, layered SPA, which is sufficient for an MVP.
Architecture Decision Rationale:
Layered Architecture: Decoupling the Media Engine (Domain) from React (Presentation) allows for easier player upgrades and prevents UI re-renders from killing the stream.
TanStack Query: Best-in-class for caching video metadata and handling infinite scroll with minimal boilerplate.
System Diagram
Architecture Deep Dive
Presentation Layer
Component Hierarchy: The
AppShell persists the GlobalPlayerManager. The Layout handles the sidebar/header. The Page components (Feed, Watch) are swapped by the Router. FeatureContainers (like the Player) manage the bridge between UI and the Media Engine.Interaction Layer: Custom controls are built using
<button> and <input type="range"> for accessibility. Input validation on Search prevents empty queries. Animations use CSS transitions for hardware acceleration.Rendering Layer: We use Client-Side Rendering (CSR) for the player to maintain state, but SSR (Next.js) is recommended for the Feed/Detail pages to optimize SEO and LCP. Virtualization (e.g.,
react-window) is mandatory for the feed.UI Frameworks: React for component management, Tailwind CSS for styling, and Radix UI for accessible primitives (dialogs, sliders).
Application Layer
Data Fetching Layer: TanStack Query handles pagination for the infinite scroll. It caches video metadata so navigating back to the feed is instantaneous.
State Management Layer:
Zustand or Redux manages the GlobalPlayerState (current video ID, playback status, volume). This allows the video to keep playing even when the user navigates from "Watch" to "Search".Routing & Navigation: Nested routes allow the "Watch" page to be a modal overlay or a standalone page. Route guards check for session tokens before allowing uploads.
Domain Layer
Business Rules: Logic for "Should this video auto-play?" based on user settings and network type (save data mode).
Entities / Models: The
Video entity maps backend JSON (snake_case) to frontend models (camelCase) and calculates formatted strings like "2.3M views" or "2 days ago".Inter-layer Contracts: The
MediaEngine provides a standard interface (play(), pause(), seek()) regardless of whether we use HLS.js or the native <video> element.Infrastructure Layer
API / Network: RESTful endpoints for metadata. CDN handles the heavy lifting of segment delivery. Request debouncing is applied to the Search bar to save bandwidth.
Storage:
localStorage stores the user's volume preference and watch history (for resume-from-last-point).Wrap Up
Wrap-up
Evaluation: The design focuses on the two biggest risks: network-efficient video playback and DOM-efficient list rendering.
Trade-offs: We chose HLS.js over native HLS for better control over buffer management in Chrome/Firefox, at the cost of a slightly larger bundle size.
Future Scale: To scale, we would introduce a BFF (Backend for Frontend) to aggregate video metadata and user status (liked/subscribed) into a single request, reducing RTT.