Channels. Live streams. Library. One streaming platform.
Consumer-facing video streaming with channel directory, live stream grid, browse by nine categories, unified search, video player with like/share/save actions, personal library with watch history and playlists, and channel subscriptions with tier pricing and entitlement verification.
,0,
client components in packages/tv-clients
,0,
content categories for browse filtering
,0,
API routes under /api/tv/
,0,
subscription status states
Hero banner. Content rows. One feed.
The home page at /tv renders a featured hero banner followed by horizontal content rows: Trending, Live Now, Recently Added, and Continue Watching. Each row is independently scrollable. The feed is assembled server-side from /api/tv/feed and includes a hero object plus an array of typed sections.
Hero Banner
Featured content spotlight at the top of the feed. Full-width image with gradient overlay, category tag, title, description, Watch Now action, and creator attribution.
Trending
Horizontally scrollable row of trending video cards. Each card shows thumbnail, duration badge, title, creator name, view count, and publish date.
Live Now
Active live streams surfaced in the feed with pulsing LIVE badge overlay. Click-through to the player. Streams appear here and on the dedicated /tv/live page.
Recently Added
Newest content from followed channels and across the platform. Chronological row updated on each page load.
Continue Watching
Videos with in-progress playback. Pink progress bar on each thumbnail shows percentage watched. One tap resumes from the last position.
Browse by category. Search by keyword.
Browse filters the full catalog across nine categories with three sort modes. Search queries videos and channels in a single debounced input. Both render from the same API layer.
Nine categories. Three sorts. One search bar.
Two paths to content. Browse filters the full catalog by category and sort order (Trending, Newest, or Most Popular) in a paginated grid. Search queries the /api/tv/search endpoint and returns videos and channels in separate result groups.
Browse
/tv/browseCategory filter pills across the top of the page. Sort toggle between Trending, Newest, and Most Popular. Responsive grid of video cards, four columns at desktop, single column at mobile. Load-more pagination in batches of 20.
- Nine content categories including All
- Three sort modes: Trending, Newest, Most Popular
- Video card: thumbnail, duration badge, title, creator, view count, publish date, category pill
- Load-more pagination (20 per page)
Search
/tv/searchUnified search input with 350ms debounce. Results split into two sections: Channels (avatar, name, subscriber count, video count) and Videos (thumbnail, title, creator, views, date). Empty state prompts a query. No-results state suggests alternatives.
- Single input, two result types
- 350ms debounce before API call
- Channel results: avatar, name, description, subscriber count, video count
- Video results: thumbnail, duration, title, creator, view count, publish date
Directory. Detail page. Four content tabs.
Channels are the organizational unit of Calisto TV. The directory at /tv/channels lists all channels with search and sort. Each channel detail page has a banner, avatar, follow/subscribe actions, and a four-tab content area: Videos, Collections, Live, and About.
Channel Directory
/tv/channelsSearchable grid of all channels. Each card shows avatar, name, description snippet, subscriber count, video count, and category. Sort by Popular or Newest. Inline search with text input.
Channel Detail
/tv/channels/[channelId]Full channel page with banner image, avatar (offset over the banner), subscriber and video counts. Two action buttons: Follow (notification bell toggle) and Subscribe (paid tier toggle). Four-tab content area below.
Channel Detail: Tab Bar
Grid of the channel's uploaded videos with thumbnail, duration, view count, and publish date.
Curated video playlists grouped by the channel creator. Each collection shows a thumbnail and video count.
Current and recent live streams from this channel. Pulsing LIVE badge and viewer count on active streams.
Channel description, four KPI stats (subscribers, videos, total views, joined date), and category badge.
Active streams. Real-time viewer counts. 30-second refresh.
The live grid auto-polls every 30 seconds. LIVE badge with pulsing dot. Viewer count overlay. Streamer avatar and category. Uptime duration. Click any card to open the player.
30-second refresh. Viewer counts. LIVE badge.
The /tv/live page shows all currently active streams in a responsive grid. The client component auto-refreshes every 30 seconds by re-fetching /api/tv/live. Each stream card displays a thumbnail with a pulsing LIVE badge, real-time viewer count, streamer avatar and name, category pill, and uptime duration.
Stream Card Anatomy
Stream preview image, full-width within the card.
Red pill with pulsing white dot in the top-left corner of the thumbnail.
Eye icon + count in a dark overlay at the bottom-right of the thumbnail.
36px circular avatar beside the stream info.
Stream title, two-line clamp.
Creator name below the title, single-line truncation.
Pink category pill (e.g., Gaming, Music).
Elapsed time since the stream started, formatted as Xh Ym.
The stream grid polls /api/tv/live every 30 seconds. No manual reload required. Viewer counts and new streams appear automatically.
A Refresh button in the page header triggers an immediate fetch. Useful when navigating back to the page.
When no streams are active, a centered empty state with a Browse Channels action links to /tv/channels.
Each stream card navigates to /tv/watch/[streamId], loading the player with the live stream URL.
Like. Share. Save. Related content.
The player page at /tv/player/[videoId] loads video detail and related content from a single API call. Below the full-width video element: metadata, three action buttons (Like with count, Share to clipboard, Save to library), creator info with channel link, description, and a horizontal row of related videos from the same channel.
Full-width aspect-video container. Native HTML5 <video> with src and poster attributes. HLS-capable via the video URL returned by /api/tv/videos/[videoId].
Title, view count, publish date, and category pill displayed below the player. Views and date use eye and calendar icons respectively.
Toggle button with current like count. Filled heart when liked, outline when not. Calls POST/DELETE to /api/tv/videos/[videoId]/like. Optimistic count update on the client.
Copies the current page URL to the clipboard via navigator.clipboard.writeText. Button text changes to "Copied" for two seconds as confirmation.
Toggle that adds or removes the video from the user's library saved list. Calls POST/DELETE to /api/tv/videos/[videoId]/save. Saved videos appear in the Library Saved tab.
Creator avatar, name, and "View channel" link. Clicking navigates to /tv/channels/[creatorId]. Avatar falls back to a pink icon circle.
Full video description rendered as pre-line whitespace text inside a card below the creator info. Only shown when a description exists.
Horizontal scrollable row of related videos from the same channel. Each card: thumbnail, duration, title, creator, view count. Clicking loads a new player page.
Watch history with progress bars. Saved videos. Custom playlists.
Three tabs in one library view. History tracks per-video progress. Saved collects bookmarks. Playlists organize content into named collections. All in a single API call to /api/tv/library.
Watch history. Saved videos. Playlists.
The user's personal library at /tv/library organizes content into three tabs. Watch History tracks playback progress with a visual progress bar on each thumbnail. Saved collects bookmarked videos. Playlists holds user-created collections. All data is fetched from /api/tv/library in a single call.
Watch History
/tv/library → history tabChronological list of watched videos. Each row shows a 160×90 thumbnail with a pink progress bar (percentage watched), title, creator name, time-ago timestamp, and a percentage label. Trash icon removes individual entries via DELETE to /api/tv/library/history/[videoId]. Clicking any row resumes playback.
Saved
/tv/library → saved tabBookmarked videos saved from the player's Save button. Same row layout as history but without the progress bar. Shows a bookmark icon with "Saved X ago" timestamp. Remove action via DELETE to /api/tv/library/saved/[videoId].
Playlists
/tv/library → playlists tabUser-created collections displayed in a two-column grid. Each card shows a cover thumbnail, playlist title, video count badge, and an "Updated X ago" timestamp. Clicking opens the playlist at /tv/library/playlists/[playlistId].
Tier pricing. Four statuses. Entitlement gate.
Channel subscriptions at /tv/subscriptions. Each subscription has a channel, tier name, price, billing cycle (monthly or yearly), renewal date, and one of four status states. Summary stats show active count and total monthly spend. The /api/tv/entitlements/check endpoint verifies content access per video based on the user's active subscriptions.
Four Subscription States
Subscription is current. Content entitlements are granted. Renewal date shown.
User has requested cancellation. Access continues until the renewal date, then the subscription expires.
Subscription has ended. Content entitlements are revoked. No further billing.
Billing is temporarily paused. Content access may be limited depending on the channel's pause policy.
Subscription Card
Avatar, channel name, and tier label. Clicking navigates to the channel detail page.
Price amount with currency and billing cycle (monthly or yearly). Displayed as "$X.XX USD/mo" or "$X.XX USD/yr".
Calendar icon with the next renewal date formatted as a localized date string.
Color-coded pill: green for Active, amber for Canceling, gray for Expired, blue for Paused.
Navigates to /tv/subscriptions/[subscriptionId] for tier changes and billing details.
Only visible for Active subscriptions. Sends DELETE to /api/tv/subscriptions/[id]. Sets status to Canceling.
Active Subscriptions
Count of subscriptions with status Active or Paused.
Monthly Total
Sum of all Active subscription prices. Displayed as $X.XX/mo.
Calisto TV is the streaming platform. Not the TV App Builder.
Two products share the word 'TV' in their names. Calisto TV (this page) is the consumer-facing streaming platform where viewers browse, watch, and subscribe. Studio's TV App Builder is the creator's pipeline for publishing branded TV apps to app stores. They are separate products with separate codebases.
Calisto TV
The streaming platform
- Consumer-facing video platform (YouTube equivalent)
- Routes: /tv/browse, /tv/channels, /tv/live, /tv/player, /tv/library, /tv/search, /tv/subscriptions
- 9 client components in packages/tv-clients/src/
- Viewers browse, watch, subscribe, and build a personal library
- Content entitlement checks per video via /api/tv/entitlements/check
- Web app at apps/tv/ with companion React Native apps for tvOS and Fire TV
Studio TV App Builder
The creator build tool
- Creator pipeline inside Calisto Studio for publishing branded TV apps
- Seven stages: Content → Design → Build → Preview → Store Listing → Analytics
- Target platforms: App Store, Google Play, Apple TV, Fire TV, Roku
- Creators configure splash screens, navigation layouts, color schemes
- Build pipeline compiles platform-specific app binaries
- Part of Studio, separate product, separate page at /products/studio
High-Performance Ops. Zero Monthly Overhead.
Get all 15 Core modules at no monthly cost. You only pay 2% of processed revenue.