Summary
The public-facing UI needs a comprehensive design overhaul to transform it from a functional video viewer into an engaging video streaming platform. While the technical foundation is solid (Alpine.js, Tailwind CSS, custom video player), the user experience lacks discovery features, personalization, and the polish expected from modern video platforms.
Current State Assessment
What Works Well
- Solid custom video player with quality switching, captions, touch gestures, PiP, keyboard shortcuts
- Clean dark theme with consistent color palette
- Responsive grid layout (1→2→3→4 columns)
- Good performance baseline with lazy loading, debounced search
- DASH/HLS adaptive streaming with Shaka Player + HLS.js fallbacks
- Well-structured player-controls.js (1,094 lines) - proves modular code is possible
Architecture Issues
- Inline CSS in watch.html: 698 lines of player CSS embedded in HTML
- Inline JavaScript: 538 lines in watch.html, similar patterns in other pages
- Code duplication: Video card markup repeated across index, category, tag pages (lines 76-96 identical)
- No component abstraction: No reusable Alpine.js components
Discovery & Navigation Gaps
- No navigation structure: Only "Home" link available
- No breadcrumbs: Users get lost on category/tag/watch pages
- Search limited to homepage: Can't search within categories
- No filtering/sorting: Can't filter by date, duration, or sort results
- No trending/featured content: Just a flat grid of latest videos
- Missing footer: No site info, links, or metadata
Missing Platform Features (vs YouTube/Vimeo)
| Feature |
Status |
| Continue Watching |
✅ Implemented (Phase 3) |
| Watch History |
✅ Implemented (localStorage) |
| Playback Speed Control |
✅ Implemented (Phase 4) |
| Theater Mode |
✅ Implemented (Phase 4) |
| Timeline Thumbnail Preview |
📋 Planned (Phase 7) |
| Video Chapters |
📋 Planned (Phase 7) |
| Share/Embed |
✅ Implemented (Phase 5) |
| Playlists |
✅ Implemented (Issue #223) |
| Related Videos Sidebar |
✅ Implemented (Phase 5) |
| View Counts |
✅ Displayed (Phase 3) |
Accessibility Issues (WCAG Failures)
Level A Failures (Critical):
- No skip-to-content link on any page
- Video player controls missing ARIA labels and states
- Progress slider lacks
role="slider" and ARIA value attributes
- Quality modal doesn't trap focus or restore focus on close
Level AA Failures (High):
- Focus indicators insufficient (1px border color change only)
- Color contrast:
text-dark-500 on dark-950 fails 4.5:1 ratio
- Touch targets 40px on mobile (should be 44px minimum)
- No screen reader announcements for dynamic content changes
Video Card Issues
No watch progress indicator on thumbnails ✅ Fixed (Phase 3)
No hover quick actions (add to queue, save) ✅ Fixed (Phase 3 - Watch Later)
Missing view counts and engagement metrics ✅ Fixed (Phase 3)
No visual distinction between watched/unwatched ✅ Fixed (progress bars show watch status)
Player UX Issues
Controls hide too quickly (3s timeout) ✅ Fixed (Phase 4 - now 5s)
No current quality indicator when set to "Auto" ✅ Fixed (Phase 4)
No playback speed control ✅ Fixed (Phase 4)
- Volume slider behavior differs desktop vs mobile
Time display shrinks to 11px on mobile (hard to read) ✅ Fixed (Phase 4)
No theater mode option ✅ Fixed (Phase 4)
Mobile Issues
- Search bar loses prominence on mobile
- Category buttons wrap awkwardly (should horizontal scroll)
- Player controls cramped on small screens
- No mobile navigation drawer
Proposed Solution
Phase 0: Accessibility Foundation ✅ COMPLETE
Critical fixes before any feature work:
Phase 1: Architecture Foundation ✅ COMPLETE (PR #481)
CSS Extraction:
JS Modularization:
Template Standardization:
Success Criteria:
Phase 2: Navigation & Structure ✅ COMPLETE (PR #482)
Code Review Fixes Applied:
Phase 3: Video Card & Discovery ✅ COMPLETE (PR #483)
Video Cards:
Homepage Redesign:
Browse Experience:
Code Review Fixes Applied:
Phase 4: Player Improvements ✅ COMPLETE (PR #484)
Player ARIA Enhancements:
Code Review Fixes Applied:
Phase 5: Watch Experience ✅ COMPLETE (PR #485)
API Additions:
Code Review Fixes Applied:
Phase 6: Accessibility Verification & Polish ✅ COMPLETE (PR #486)
Code Review Fixes Applied:
Phase 7: Advanced Player Features (Timeline Thumbnails & Chapters)
Timeline Thumbnail Preview:
Video Chapters:
Technical Approach:
- FFmpeg sprite generation:
ffmpeg -i input.mp4 -vf "fps=0.1,scale=160:-1,tile=10x10" sprites.jpg
- WebVTT thumbnails format is widely supported
- Shaka Player has native support:
addThumbnailsTrack() and addChaptersTrack()
| Sub-feature |
Complexity |
Dependencies |
| Timeline Thumbnails |
High |
Transcoder changes, storage, player UI |
| Video Chapters |
Medium |
Database migration, admin UI, player UI |
API Requirements
New Endpoints Needed:
- ✅
GET /api/videos/:slug/related - Related videos for sidebar (Phase 5)
GET /api/videos/trending - Trending/popular videos (or add to existing endpoint)
Phase 7 Endpoints:
GET /api/videos/:id/thumbnails - Thumbnail sprite sheet URL and metadata
GET /api/videos/:id/chapters - Chapter list for a video
POST /api/videos/:id/chapters - Add chapter (admin)
PUT /api/videos/:id/chapters/:chapter_id - Update chapter (admin)
DELETE /api/videos/:id/chapters/:chapter_id - Delete chapter (admin)
Existing Endpoint Modifications:
GET /api/videos - Add sort param (date, views, relevance)
GET /api/videos - Add filter params (duration_min, duration_max, uploaded_after)
- Video responses should include
view_count field
Client-Side State Architecture
localStorage Schema:
{
"vlog:watch-history": {
"video-id-1": { position: 120, duration: 600, lastWatched: "2024-01-15T..." },
"video-id-2": { position: 45, duration: 300, lastWatched: "2024-01-14T..." }
},
"vlog:preferences": {
"playbackSpeed": 1.0,
"autoplay": true,
"defaultQuality": "auto",
"theaterMode": false
}
}
Utility API (add to VLogUtils):
VLogUtils.watchHistory.get(videoId) // ✅ Implemented
VLogUtils.watchHistory.save(videoId, position, duration) // ✅ Implemented
VLogUtils.watchHistory.clear(videoId) // ✅ Implemented
VLogUtils.watchHistory.getAll() // ✅ Implemented
VLogUtils.preferences.get(key) // Pending
VLogUtils.preferences.set(key, value) // Pending
File Structure (Current State after Phase 5)
web/public/
├── static/
│ ├── css/
│ │ ├── design-tokens.css # ✅ CSS custom properties
│ │ ├── a11y.css # ✅ Accessibility utilities
│ │ ├── bundle.css # ✅ Main entry point
│ │ ├── components/
│ │ │ └── video-card.css # ✅ Video card styles (BEM)
│ │ └── pages/
│ │ └── player.css # ✅ Player + theater + share modal + watch layout
│ └── js/
│ ├── pages/
│ │ └── watch.js # ✅ Watch page + resume + related videos
│ ├── utils.js # ✅ + watchHistory utility
│ └── player-controls.js # ✅ + speed/theater/shortcuts/share
Design Tokens
:root {
/* Colors - Semantic Roles */
--color-bg-primary: #0a0a0b; /* dark-950 */
--color-bg-secondary: #18181b; /* dark-900 */
--color-bg-elevated: #27272a; /* dark-800 */
--color-text-primary: #f4f4f5; /* dark-100 */
--color-text-secondary: #a1a1aa; /* dark-400 */
--color-text-muted: #71717a; /* dark-500 - use sparingly, contrast issues */
--color-accent: #3b82f6; /* blue-500 */
--color-accent-hover: #60a5fa; /* blue-400 */
/* Spacing Scale */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
/* Transitions */
--transition-fast: 150ms ease;
--transition-normal: 300ms ease;
/* Focus */
--focus-ring: 2px solid var(--color-accent);
--focus-offset: 2px;
}
Accessibility Testing Checklist
Automated Testing
Manual Testing
Screen Reader Scenarios
Success Metrics
Architecture:
Accessibility:
Features:
Benchmark Comparison
| Feature |
Current |
Target |
YouTube |
Vimeo |
| Featured content |
✅ |
✅ |
✅ |
✅ |
| Continue watching |
✅ |
✅ |
✅ |
✅ |
| Playback speed |
✅ |
✅ |
✅ |
✅ |
| Theater mode |
✅ |
✅ |
✅ |
✅ |
| Share buttons |
✅ |
✅ |
✅ |
✅ |
| Watch history |
✅ |
✅ |
✅ |
✅ |
| Related videos |
✅ |
✅ |
✅ |
✅ |
| Resume playback |
✅ |
✅ |
✅ |
✅ |
| Keyboard nav |
✅ |
✅ |
✅ |
✅ |
| Screen reader |
✅ |
✅ |
✅ |
✅ |
| Skip link |
✅ |
✅ |
✅ |
✅ |
| Focus indicators |
✅ |
✅ |
✅ |
✅ |
| Timeline thumbnails |
❌ |
📋 Phase 7 |
✅ |
✅ |
| Video chapters |
❌ |
📋 Phase 7 |
✅ |
✅ |
References
Summary
The public-facing UI needs a comprehensive design overhaul to transform it from a functional video viewer into an engaging video streaming platform. While the technical foundation is solid (Alpine.js, Tailwind CSS, custom video player), the user experience lacks discovery features, personalization, and the polish expected from modern video platforms.
Current State Assessment
What Works Well
Architecture Issues
Discovery & Navigation Gaps
Missing Platform Features (vs YouTube/Vimeo)
Accessibility Issues (WCAG Failures)
Level A Failures (Critical):
role="slider"and ARIA value attributesLevel AA Failures (High):
text-dark-500ondark-950fails 4.5:1 ratioVideo Card Issues
No watch progress indicator on thumbnails✅ Fixed (Phase 3)No hover quick actions (add to queue, save)✅ Fixed (Phase 3 - Watch Later)Missing view counts and engagement metrics✅ Fixed (Phase 3)No visual distinction between watched/unwatched✅ Fixed (progress bars show watch status)Player UX Issues
Controls hide too quickly (3s timeout)✅ Fixed (Phase 4 - now 5s)No current quality indicator when set to "Auto"✅ Fixed (Phase 4)No playback speed control✅ Fixed (Phase 4)Time display shrinks to 11px on mobile (hard to read)✅ Fixed (Phase 4)No theater mode option✅ Fixed (Phase 4)Mobile Issues
Proposed Solution
Phase 0: Accessibility Foundation ✅ COMPLETE
Critical fixes before any feature work:
role="search"landmark to search regionPhase 1: Architecture Foundation ✅ COMPLETE (PR #481)
CSS Extraction:
/static/css/design-tokens.csswith CSS custom properties/static/css/pages/player.css/static/css/components/video-card.cssa11y.css,bundle.css)JS Modularization:
watchPage()logic to/static/js/pages/watch.jsAlpine.data()registration for watchPage componentutils.jsTemplate Standardization:
Success Criteria:
Phase 2: Navigation & Structure ✅ COMPLETE (PR #482)
Code Review Fixes Applied:
Phase 3: Video Card & Discovery ✅ COMPLETE (PR #483)
Video Cards:
aria-labelwith full context for screen readersHomepage Redesign:
Browse Experience:
Code Review Fixes Applied:
Phase 4: Player Improvements ✅ COMPLETE (PR #484)
Player ARIA Enhancements:
aria-pressedstates to toggle buttons (play, mute, captions, fullscreen)aria-labeldynamically based on statearia-valuetextto sliders with human-readable valuesCode Review Fixes Applied:
Phase 5: Watch Experience ✅ COMPLETE (PR #485)
API Additions:
GET /api/videos/{slug}/related- Smart recommendations (category + tags algorithm)Code Review Fixes Applied:
Phase 6: Accessibility Verification & Polish ✅ COMPLETE (PR #486)
prefers-reduced-motionsupport (added in Phase 5)Code Review Fixes Applied:
Phase 7: Advanced Player Features (Timeline Thumbnails & Chapters)
Timeline Thumbnail Preview:
Video Chapters:
Technical Approach:
ffmpeg -i input.mp4 -vf "fps=0.1,scale=160:-1,tile=10x10" sprites.jpgaddThumbnailsTrack()andaddChaptersTrack()API Requirements
New Endpoints Needed:
GET /api/videos/:slug/related- Related videos for sidebar (Phase 5)GET /api/videos/trending- Trending/popular videos (or add to existing endpoint)Phase 7 Endpoints:
GET /api/videos/:id/thumbnails- Thumbnail sprite sheet URL and metadataGET /api/videos/:id/chapters- Chapter list for a videoPOST /api/videos/:id/chapters- Add chapter (admin)PUT /api/videos/:id/chapters/:chapter_id- Update chapter (admin)DELETE /api/videos/:id/chapters/:chapter_id- Delete chapter (admin)Existing Endpoint Modifications:
GET /api/videos- Addsortparam (date, views, relevance)GET /api/videos- Addfilterparams (duration_min, duration_max, uploaded_after)view_countfieldClient-Side State Architecture
localStorage Schema:
Utility API (add to VLogUtils):
File Structure (Current State after Phase 5)
Design Tokens
Accessibility Testing Checklist
Automated Testing
Manual Testing
Screen Reader Scenarios
Success Metrics
Architecture:
Accessibility:
Features:
Benchmark Comparison
References