Skip to content

Repository files navigation

VMP (Video Monetization Platform)

Subscription-gated HLS video streaming: Cloudflare Worker API + Nuxt 4 web app, with optional Deno backup API and a media VM for transcoding.

Contents

Architecture

Layer Technology
API Cloudflare Worker (@vmp/api) — REST, auth, Stripe, push, RSS
Web Nuxt 4 / Vue 3 (@vmp/web) — Cloudflare Workers SSR (vmp-web-worker-dev / vmp-web-worker-prod)
Database Cloudflare D1 (SQLite); Postgres shim on Deno backup
Object storage Cloudflare R2 (pluggable via @vmp/storage)
Payments Stripe (+ optional legacy Qerko via @vmp/payments)
Email / push Brevo transactional, Web Push (VAPID)
Transcoding @vmp/media-pipeline on a media VM (SVT Encore + Shaka → R2)
Backup API @vmp/api-node on Deno Deploy (same handlers, Postgres + S3)

Cloudflare Pages (vmp-fe) is deprecated. Do not attach production hostnames to Pages.

Browser ──► @vmp/web (Worker SSR)
                │
                ▼
           @vmp/api (Worker) ──► D1 / R2 / KV
                │
                ├── Stripe webhooks, Brevo, Web Push
                └── pipeline-status ◄── @vmp/media-pipeline (VM)

Monorepo packages

Package Path Role
@vmp/api packages/api Primary Cloudflare Worker API
@vmp/web packages/web Nuxt 4 frontend (Workers SSR)
@vmp/shared packages/shared Shared TypeScript types
@vmp/storage packages/storage Pluggable object storage (R2 / S3-compatible) — README
@vmp/payments packages/payments Payment provider registry (Stripe, legacy Qerko) — README
@vmp/api-node packages/api-node Deno Deploy backup API — README
@vmp/media-pipeline packages/media-pipeline Media VM: Encore + Shaka HLS + R2 — README
@vmp/offloading packages/offloading R2 ↔ Garage hot/cold tiering — README
@vmp/moq-probe packages/moq-probe MoQ live broadcast diagnostic probe — README

Core API/web packages do not ship separate READMEs; see AGENTS.md for auth, D1 schema, roles, and agent workflow.

Documentation

Document Audience
AGENTS.md Canonical architecture, git workflow, secrets, local Cloud setup, roadmap
DEPLOYMENT.md CI/CD, env vars, smoke checks, bootstrap / rollback
docs/README.md Index of API notes and historical design docs
packages/web/docs/workers-deploy-env.md Web Worker build-time env vars
Package READMEs under packages/* Package-specific ops (pipeline, api-node, storage, …)

Prerequisites

  1. Node.js 20+ and npm 10+ (packageManager in root package.json).
  2. Cloudflare account with Workers, D1, R2, and KV (per environment).
  3. CI deploy secrets: CLOUDFLARE_API_TOKEN_{STAGING,PROD} and CLOUDFLARE_ACCOUNT_ID_{STAGING,PROD}.

Local development

npm ci
npm run typecheck

# API (Wrangler, port 8787) — needs packages/api/.dev.vars
npm run dev --workspace=@vmp/api

# Web (Nuxt, port 3000)
API_URL=http://localhost:8787 npm run dev --workspace=@vmp/web

Apply D1 migrations locally before serving data:

cd packages/api
for f in $(ls -1 migrations/*.sql | sort); do
  npx wrangler d1 execute video-subscription-db --local --file="$f"
done

Seed videos start as drafts. To publish them for the homepage:

npx wrangler d1 execute video-subscription-db --local \
  --command="UPDATE videos SET publish_status = 'published', published_at = CURRENT_TIMESTAMP WHERE publish_status = 'draft';"

Full Cloud-agent local notes (secrets, gotchas): AGENTS.md → Cursor Cloud-specific instructions.

Deploy

Trigger What deploys
Push to main Staging: API Worker + web Worker (vmp-web-worker-dev) via .github/workflows/deploy.yml
Tag v*.*.* Production: API Worker + web Worker (vmp-web-worker-prod)
Push / PR (Deno git integration) @vmp/api-node preview/production build on Deno Deploy — not from deploy.yml. PR check status is pending until deploy/tjm/vmp clears; maintainer log review on console.deno.com is required when that check stays red.

Manual commands:

npm run deploy:api
npm run deploy --workspace=@vmp/web          # staging Worker
npm run deploy:prod --workspace=@vmp/web     # production Worker

Deploy gates typecheck @vmp/shared, @vmp/storage, @vmp/api, and @vmp/web before build. Details: DEPLOYMENT.md.

Never push feature work directly to main — use a branch + pull request (autodeploy + CodeRabbit). See AGENTS.md → Git workflow.

Secrets and configuration

  • Template: root .env.example. Copy to .env.staging / .env.production as needed.
  • Local API secrets: packages/api/.dev.vars (never commit).
  • Required Worker secrets (JWT, Stripe, Brevo, VAPID, RSS, TOTP, …): listed in AGENTS.md and DEPLOYMENT.md.
  • Prices, plan names, and limits live in D1 admin_settings — not hardcoded.

Media encoding

Transcoding runs on a media VM via @vmp/media-pipeline:

  1. Watchfolder intake → SVT Encore encode
  2. encore-packager (Shaka) → fMP4 HLS ladder uploaded to R2
  3. HMAC callback to POST /api/admin/videos/:id/pipeline-status

There is no AWS Elemental MediaConvert admin upload/transcode UI in this repo anymore. The historical media_convert_jobs D1 table remains: playback and offline-download code may still read completed Bunny Stream rows (provider = 'bunnystream', bunny_playback_url) as an alternate HLS entrypoint. Do not drop that table without a migration that replaces those reads.

About

Video Monetization Platform - HLS video streaming with subscription-based access control

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Used by

Contributors

Languages