Skip to content

Repository files navigation

HasanHub

HasanHub preview

HasanHub is a web app that aggregates videos from multiple YouTube channels into one view. Tags can be added centrally and are then auto-detected across synced videos.

The original project launched in April 2022 and is documented here: chrcit.com/projects/hasanhub-com

This is still a raw release with basic documentation. There is currently no admin UI for editing data. Non-dynamic data needs to be inserted directly into the database.

What is this?

HasanHub is a YouTube aggregator for the Hasanabi Clips Industrial Complex.

Political streamer Hasanabi allows fans to clip stream VODs, upload those clips to YouTube, and build fan channels around them. Over time this created a large ecosystem of Hasan-related channels. HasanHub pulls videos from those channels into a single feed so users can browse clips across the whole network instead of hopping between individual channels.

Why?

Hasan's community is a particularly good fit for this kind of product because there are so many fan channels and so much backlog spread across them.

But the idea is broader than Hasanabi. This setup can also work for other creators or communities that have:

  • multiple affiliated channels
  • a fragmented video archive
  • a need for unified discovery, tagging, and filtering

Features

  • Aggregate videos from many channels into one feed
  • Filter by tags, duration, timeframe, and ordering
  • Auto-match tags against synced videos
  • Show sidebar tag discovery based on views
  • Expose Twitch stream status and schedule data
  • Publish stats and sitemap routes
  • Run scheduled sync jobs for channels, videos, and tag matching

Stack

Frontend:

  • TypeScript
  • React 19
  • React Router 7 with SSR
  • Tailwind CSS v4

Backend:

  • Cloudflare Workers
  • Cloudflare D1 (SQLite) with Drizzle ORM
  • Workers Cache (CDN) driven by Cache-Control headers
  • YouTube and Twitch integrations

Tooling:

  • pnpm
  • Wrangler
  • Drizzle Kit
  • Vite

Development

pnpm install
pnpm dev

The local dev server runs at http://localhost:5173.

Other useful commands:

pnpm build
pnpm typecheck
pnpm db:generate
pnpm db:migrate
pnpm db:migrate:remote
pnpm db:validate
pnpm db:studio

Configuration

This app is configured as a Cloudflare Worker in wrangler.jsonc.

Important bindings and environment values:

  • DB: Cloudflare D1 database
  • YOUTUBE_API_KEY: YouTube sync client
  • TWITCH_CLIENT_ID: Twitch API client ID
  • TWITCH_CLIENT_SECRET: Twitch API client secret
  • TOP_OF_THE_HOUR_SECRET: secret for the rating endpoint
  • CLOUDFLARE_ACCOUNT_ID: required by Drizzle Kit
  • CLOUDFLARE_D1_ID: required by Drizzle Kit
  • CLOUDFLARE_TOKEN: required by Drizzle Kit

Data Model And Editing

There is no admin panel yet.

That means operational data like channels, tags, and other non-dynamic records need to be managed directly in D1. Synced data such as videos and channel metadata is then refreshed through the app's sync tasks.

Relevant schema lives in db/schema.ts.

Sync Jobs

The worker has scheduled jobs defined in app/cron/jobs.ts:

  • syncNewVideos: every 15 minutes
  • syncVideos: every hour
  • syncChannels: daily at 03:00
  • matchTags: daily at 04:00

These jobs keep the dataset current and apply tag matching after sync.

Caching

Caching is entirely CDN-side via Workers Cache (cache.enabled in wrangler.jsonc). Routes set Cache-Control with max-age + stale-while-revalidate (use max-age, not s-maxage, so SWR works at the edge). Cloudflare serves hits without running the Worker.

TTLs mirror the old KV query-cache windows:

  • /max-age=20minutes, stale-while-revalidate=1day
  • /tags/*max-age=6hours for browsers, max-age=72hours for crawlers (isbot / empty UA), stale-while-revalidate=1week for both. No Vary: User-Agent so the CDN is not fragmented per browser.
  • layout / sidebar / tags API — max-age=1day, stale-while-revalidate=1week
  • /statsmax-age=1hour, stale-while-revalidate=1day
  • /sitemap.xml / robots.txtmax-age=1day, stale-while-revalidate=1week
  • stream info API — max-age=15minutes, stale-while-revalidate=1hour

Database Scripts

There are helper scripts for local and remote D1 workflows:

  • pnpm db:generate
  • pnpm db:migrate
  • pnpm db:migrate:remote
  • pnpm db:import:remote-to-local
  • pnpm db:import:local-to-remote

About

Hasanhub is a Youtube aggregator for over 70 channels in the Hasanabi Clips Industrial Complex.

Topics

Resources

Stars

15 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages