Reading from the channels query cache was unreliable (cache might not be
loaded, or channel not followed). Add c.thumbnail_url AS channel_thumbnail_url
to _VIDEO_SELECT so every video response carries its channel avatar directly.
VideoCard uses it with cache as fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Card wrapper overflow-hidden was clipping description text at the card
boundary. Move overflow-hidden + rounding to the thumbnail only so the
card body text has room to render fully.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Date and views share a meta line; description shows up to 2 lines below —
gives enough context to judge a video during discovery without opening it.
Both fields are optional so cards without them stay compact.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VideoCard grid: YouTube-style layout — channel avatar circle (falls back
to letter) left of title/meta, avatar is clickable to go to channel page,
date on its own line for breathing room, badges inline with channel name
Bottom nav: env(safe-area-inset-bottom) so it clears iOS home indicator,
active tab gets a soft accent pill behind the icon, slightly bolder label
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add bottom tab bar (Home/Following/Discover/Downloads/Settings) for mobile
- Fetch and display channel banner images on channel pages
- Fix ChannelCard: channels without a local DB id now follow+navigate on click
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Self-hosted personal YouTube management app.
FastAPI + SQLite backend, React + Vite + Tailwind frontend.
Dockerfiles and compose included for Portainer deployment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>