Skip to main content

Cloudflare Worker Handbook

The qubital-upload-pipeline Worker listens for LiveKit egress_ended webhooks, pulls the recording from R2, and uploads it to YouTube — notifying Google Sheets and Slack on completion.


1. Overview​

Project Structure

The project is a pnpm monorepo with the following key components:

  • package.json (Root): Contains workspace definitions and high-level scripts for deploying specific workers
  • pkg/upload-worker/: The directory for this specific worker
    • package.json: Defines worker-specific dependencies and scripts. The name field here is what pnpm --filter uses
    • wrangler.toml: Configuration for the deployed worker service name, compatibility dates, and local-only variables
  • pkg/shared/: A shared library for common code like types and middleware

2. Prerequisites & Credential Gathering​

Wrangler is the official CLI tool for managing Cloudflare Workers. It is a devDependency in our project, so it will be installed automatically with our other project dependencies.

Requirements:

  • Node.js (≥22)
  • pnpm package manager

2.1. Cloudflare​

  • Cloudflare Account: You need an active account.

  • R2 Bucket: Go to R2 in the dashboard and create a new bucket (e.g., my-project-recordings) with default options. Note the bucket name.

  • R2 API Token:

  1. Go to R2 → Manage R2 API Tokens
  2. Click Create API Token
  3. Give it a name and select Read & Write permissions
  4. Click Create API Token and copy the Account ID, Access Key ID, and Secret Access Key. Store them securely

Gather all this information as you'll need:

  • Bucket name
  • Access Key ID (key)
  • Secret Access Key (secret)
  • Region (set to auto)
Important

Save the R2 endpoint without the extension in the URL (e.g., https://123abc.r2.cloudflarestorage.com). DO NOT add /your-storage-name at the end, as it will break the upload process by searching for a nested folder that doesn't exist.

2.2. LiveKit​

  • LiveKit Cloud Project: You need an active project.

  • API Credentials:

  1. In your LiveKit Cloud project, go to Settings → Keys
  2. Copy the API Key and API Secret. Store them securely
  3. Copy the Host / URL (e.g., wss://my-project.livekit.cloud)

Gather all this information as you'll need:

  • LiveKit API Key
  • LiveKit API Secret
  • LiveKit URL

3. Cloudflare Configuration & Deployment​

This phase connects your code to the Cloudflare platform.

3.1. Create the Worker Project​

  1. In the Cloudflare dashboard, go to Workers & Pages
  2. Click Create application → Import a Repository
  3. Select your GitHub repository
  4. In the build settings, choose Cloudflare Workers as the framework

Build Settings:

  • Build command: (leave empty)
  • Deploy command: pnpm install && pnpm deploy:upload:staging
  • Root directory: /
  1. Click Save and Deploy

Note: The first deployment will fail because it's missing environment variables. This is expected.

3.2. Configure Environment Variables & Secrets​

  1. Go to your newly created worker's Settings → Variables and Secrets
  2. All credentials and configuration must be set in the dashboard
  3. Secrets (e.g., API keys, auth tokens) must be encrypted by checking the Secret box
warning

A typo or a missing variable here is the #1 cause of deployment failures. Double-check everything. When deploying with GitHub automation, it will remove all plain text vars, so we put all vars as Secrets.

4. Connecting LiveKit​

The final step is to tell LiveKit where to send its webhooks.

Setup Steps

  1. Go to your project in the LiveKit Cloud Dashboard
  2. Navigate to Settings → Webhooks
  3. Click Add Webhook
  4. Webhook URL: Enter the URL of your deployed worker:
https://qubital-upload-pipeline-staging.your-subdomain.workers.dev/livekit/webhook
warning

When you configure the webhook in the LiveKit Cloud dashboard, you must provide the full, complete URL to your worker's endpoint. For this project, the correct format is:

https://<your-worker-name>.<your-subdomain>.workers.dev/livekit/webhook

Be sure to include the /livekit/webhook path at the end, as this is the specific route our Hono application is listening on.

5. Final Deployment and Verification​

Deployment Steps

  1. Commit all your code changes (like the wrangler.jsonc name update) and push to your GitHub repository's staging branch
  2. This will trigger a new deployment in the Cloudflare dashboard
  3. Watch the deployment log. It should now succeed

End-to-End Test

Perform the following test to verify everything is working:

  1. Start a LiveKit session in your application
  2. Trigger a recording via your Go backend
  3. Stop the recording
  4. Wait a minute or two
  5. Check for:
    • A new unlisted video on your YouTube channel
    • A new row in your Google Sheet
    • A notification in your Slack channel

Appendix: Troubleshooting​

Common Issues

Seeing an OLD BUILD?

Solution: Go to Settings → Builds & deployments → Clear build cache in Cloudflare and retry the deployment.

Deployment Fails with Reserved Command Errors?

Solution: Ensure your worker's deploy script is not named deploy or publish (e.g., use deploy:wrangler).

Worker Fails with "Resolved credential object is not valid"?

Solution: You are missing one or more secrets/variables in the Cloudflare dashboard settings. Double-check all required environment variables.

Worker Fails with "NoSuchKey" from R2?

Solution: This means the file wasn't found. Check that:

  • Your LiveKit Server's config.yaml is pointing to the correct R2 bucket
  • Your Go backend's filepath template is a relative path (e.g., out/...)