Skip to content

muxinc/mux-convex-component

Repository files navigation

Mux Convex Component

A reusable Convex component for apps that use Mux for video. Sync your Mux video data with Convex and build video apps with a real-time database backing your catalog.

This package gives you:

  • Convex tables for Mux assets, uploads, liveStreams, and events
  • Mutations to upsert/delete synced Mux objects
  • App-level videoMetadata storage (userId, title, visibility, tags, custom fields)
  • Query helpers for catalog and user-facing video data
  • A separate companion CLI package, @mux/convex-mux-init, to scaffold app-level Convex wrappers (npx convex-mux-init)

Quickstart

1) Install packages

npm i @mux/convex @mux/mux-node
npm i -D @mux/convex-mux-init

If you prefer not to install the scaffold CLI, you can run it directly with npx:

npx @mux/convex-mux-init@latest --component-name mux

2) Generate app-level Convex files

npx convex-mux-init --component-name mux

# or without installing it
npx @mux/convex-mux-init@latest --component-name mux

This creates:

  • convex/convex.config.ts
  • convex/migrations.ts
  • convex/muxWebhook.ts
  • convex/muxHttp.ts
  • convex/http.ts if your app does not already have one

If files already exist, the CLI skips them unless you pass --force. Existing convex/http.ts is never overwritten.

3) Set Mux API env vars in Convex

npx convex env set MUX_TOKEN_ID <your_mux_token_id>
npx convex env set MUX_TOKEN_SECRET <your_mux_token_secret>

4) Start Convex and run backfill

npx convex dev
npx convex run migrations:backfillMux '{}'

5) Register the webhook route

If npx convex-mux-init created convex/http.ts for you, this is already done.

If your app already had convex/http.ts, wire the generated helper into your existing router:

import { httpRouter } from "convex/server";
import { registerMuxHttpRoutes } from "./muxHttp";

const http = httpRouter();

registerMuxHttpRoutes(http);

export default http;

6) Configure Mux webhook endpoint

In the Mux dashboard, create a webhook endpoint:

  • URL for deployed app: https://<your-deployment>.convex.site/mux/webhook
  • URL for local development: use a tunnel (e.g. ngrok or cloudflared) to /mux/webhook

Copy the webhook signing secret and set it in Convex:

npx convex env set MUX_WEBHOOK_SECRET <your_mux_webhook_secret>

7) Verify data in Convex dashboard

Tables to check:

  • assets
  • uploads
  • liveStreams
  • events
  • videoMetadata

Why both backfill and webhook?

  • Backfill is a one-time catch-up for existing Mux objects.
  • Webhooks keep your Convex tables updated in near real time as Mux state changes.

Without webhooks, data will drift over time.

Runtime model

This follows Convex component best practices:

  • @mux/convex is component-only (schema, queries, mutations)
  • Node runtime integration (Mux SDK, webhook verification, backfill) lives in app-level code in your project
  • @mux/convex-mux-init is the separate CLI package that scaffolds those app-level files for you

Using a different component name

If you mount with a different name, for example:

app.use(mux, { name: "videoInfra" });

Then regenerate wrappers with the matching name:

npx convex-mux-init --component-name videoInfra --force

Common commands

# regenerate wrappers
npx convex-mux-init --component-name mux --force

# run backfill with options
npx convex run migrations:backfillMux '{"maxAssets":500,"defaultUserId":"dev-user-1","includeVideoMetadata":true}'

# run against prod deployment
npx convex run --prod migrations:backfillMux '{"maxAssets":500}'

Troubleshooting

  • Could not find function for 'migrations:backfillMux': Ensure convex/migrations.ts exists and exports backfillMux, then run npx convex dev.
  • InvalidReference ... does not export [mux_node.backfillAssets]: Do not call components.<name>.mux_node.* directly. Use the app-level wrappers generated by npx convex-mux-init.
  • TypeScript webhooks.unwrap ... Record<string, unknown>: Regenerate wrappers with npx convex-mux-init --force.
  • TypeScript request.headers.entries is not a function/property: Build headers with request.headers.forEach(...) in convex/muxHttp.ts.
  • Webhooks route compiles but never updates tables: If ingestMuxWebhook is generated as internalAction, call it via internal.muxWebhook.ingestMuxWebhook (not anyApi.*).
  • Node APIs without "use node": Ensure Node runtime files start with "use node";.
  • Bundling fails on node:fs / node:path from @mux/convex/bin/*: Upgrade to the split packages and use @mux/convex-mux-init as the separate scaffold CLI.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors