Web Application

tooby.us

It's a tool that allows parents to control which YouTube channels their kids can access. Kids can request channels, and both parents must approve them. The app also lets kids watch their favorite channels and videos without ads.

Tech Stack

Next.jsSupabaseTypeScriptPostgreSQLShadcnTailwind CSS
TimelineOct - Dec 2025
RoleFull Stack
ClientDirect
StatusLive

What is this project?

This project is a Next.js / React web app that lets authenticated users manage a curated YouTube experience, with a focus on separating parent-facing controls from child-facing consumption. It integrates Supabase for authentication, data storage, and edge functions, and uses the YouTube Data API to fetch and cache channel and video metadata. Stripe is wired in for subscription/billing, but the specific commercial rules are kept out of the code explanation here.

High-level features

Parent & child spaces

  • Parent layout and pages for managing accounts, channels, API keys, and other settings.
  • Child layout and pages (e.g. slug-based child URLs) focused on browsing and watching curated channel content, with a simplified UI (e.g. channel tiles, per‑child theming).

Channel & video curation

  • Assign YouTube channels to a child and persist that relationship in Supabase.
  • Store and reuse channel metadata and playlists, and persist video metadata in a channel_video table for faster subsequent access.
  • Search and filter videos by title, with optional fallback to direct YouTube API search when needed.

Account, subscription, and API key management

  • Supabase Auth for sign‑in and user context.
  • Subscription and product retrieval via Supabase tables, with Stripe utilities for payment flows.
  • Per‑user YouTube API key storage, with logic to fall back from child to parent when appropriate (without exposing the underlying business rules here).

Content approval and workflows

  • Structures for managing “approval” around adding channels, plus email templates for notifications (e.g. channel approval emails).
  • Background function invocation (Supabase functions) to sync YouTube content without blocking the user.

Efficiency & performance work

The codebase includes several deliberate efficiency optimizations to keep the app responsive and API usage reasonable:

  • Server-side caching with react.cache
    • Many Supabase query helpers are wrapped in cache(...).
    • This memoizes identical server calls during a render pass, avoiding redundant database and API hits when the same data is requested multiple times.
  • Channel and video data caching in the database
    • Channel metadata fetched from YouTube is persisted in Supabase (channel.channel_data) and re-used on subsequent requests instead of always hitting the YouTube API.
    • Video lists are stored in a channel_video table, with:
      • Paginated access (getChannelVideosFromDBPaginated) using limit and published_at cursoring.
      • Upsert on save (saveVideosToDatabase) with onConflict on (channel_id, youtube_video_id) to avoid duplicates.
    • There is a dedicated checkForNewVideos helper that compares the latest DB video timestamp to the latest playlist item from YouTube to decide whether a refresh is needed, instead of always refetching.
  • Background “fire‑and‑forget” syncing
    • triggerFetchYoutubeVideos calls a Supabase edge function (fetch-youtube-videos) without awaiting completion, offloading heavy sync work to a background process so user requests aren’t blocked.
  • Debounced and batched client behavior
    • Search in SearchableVideoList is debounced (via lodash/debounce) so keystroke‑level queries don’t spam server actions or external APIs.
    • Infinite scroll / pagination is also debounced and only triggers when the user is near the bottom of the page, reducing unnecessary fetches during rapid scrolling.
    • Paginated fetching uses small batch sizes and “has more” flags (nextPageToken, hasMoreResultsRef, isEndOfPage) to avoid over-fetching.
  • Deduplication and normalization
    • Video lists are passed through a deduplicateVideos helper keyed by a normalized video ID, ensuring that merged results from different sources (Supabase vs YouTube API) don’t produce duplicate entries or extra re-renders.
  • API key and quota awareness
    • API keys are looked up once per request, with child→parent fallback where appropriate, to minimize repeated key lookups.
    • YouTube search and load more logic explicitly tracks and short‑circuits on 403 / quota issues, avoiding wasteful repeated attempts when the external quota has been exceeded.