Build a video sharing app with StreamGate

A self-hostable video sharing web app built on Next.js and powered by FastPix. Upload videos or record your screen and camera directly in the browser — get a permanent shareable link in seconds, no database required.

StreamGate is a self-hosted video sharing web app built with Next.js and powered by FastPix. It lets users upload videos or record their screen and camera in the browser, then share a permanent link within seconds. No database is required.

Live demo: streamgate.dev


Overview

StreamGate implements a complete video upload and playback workflow using FastPix APIs. Key capabilities include:

  • Drag-and-drop file uploading with a progress bar
  • In-browser screen and camera recording through the MediaRecorder API
  • Adaptive HLS playback delivered over FastPix's global CDN with an adaptive bitrate ladder
  • Webhook event handling for asset lifecycle events
  • Permanent shareable URLs for every uploaded video

Before you begin

System requirements

RequirementVersionNotes
Node.js18 or laterUse Node.js 20 LTS for best compatibility with Next.js 16
Package managerLatestnpm, pnpm, or yarn
FastPix accountRequiredProvides API credentials and media storage
Internet connectionRequiredRequired for API calls and media delivery

Get your FastPix API credentials

FastPix APIs use HTTP Basic Auth. Your Access Token ID is the username; your Secret Key is the password.

To generate credentials:

  1. Log in to the FastPix Dashboard.
  2. Go to Manage → Access Tokens.
  3. Copy your Access Token ID and Secret Key.

For detailed steps, see Authentication with Basic Auth.


Set up StreamGate

Clone the repository and install dependencies

git clone https://github.com/FastPix/streamGate.git
cd streamGate
npm install

Configure environment variables

Create a .env.local file in the project root:

touch .env.local

Add the following variables:

FASTPIX_ACCESS_TOKEN_ID=your-access-token-id
FASTPIX_SECRET_KEY=your-secret-key
FASTPIX_WEBHOOK_SECRET=your-webhook-secret
NEXT_PUBLIC_BASE_URL=http://localhost:3000

WARNING:

Never commit .env.local to version control. The file is already listed in .gitignore.

For a full description of each variable, see Environment variables reference.


Start the development server

npm run dev

Open http://localhost:3000 in your browser.


Routes and API endpoints

Upload

MethodRouteDescription
POST/api/uploadsCreates a signed FastPix upload URL; returns uploadId and url
GET/api/uploads/[id]Polls upload status; returns mediaId when the asset is created
GET/api/assets/[id]Returns asset status and playbackId when processing is complete

Playback

RouteDescription
/v/[mediaId]Watch page that embeds the FastPix HLS player with Open Graph metadata

Recording

RouteDescription
/recordIn-browser recording page; supports screen capture and webcam

Webhooks

MethodRouteDescription
POST/api/webhooks/fastpixVerifies HMAC-SHA256 signatures and handles FastPix asset lifecycle events

Integrate StreamGate into an existing app

You don't need to run StreamGate as a standalone project. You can copy individual parts into your own codebase.

Option A: Copy the API routes (backend only)

Copy the following files into your Next.js project for server-side FastPix integration:

lib/fastpix.ts
app/api/uploads/route.ts
app/api/uploads/[id]/route.ts
app/api/assets/[id]/route.ts
app/api/webhooks/fastpix/route.ts     # optional

Install the FastPix Node SDK:

npm install @fastpix/fastpix-node

Then call the routes from your existing frontend:

// 1. Get a signed upload URL
const { uploadId, url } = await fetch('/api/uploads', { method: 'POST' }).then(r => r.json());

// 2. Upload the file directly to FastPix
await fetch(url, {
  method: 'PUT',
  body: file,
  headers: { 'Content-Type': file.type }
});

// 3. Poll until the asset is ready (2-minute timeout)
let mediaId;
for (let i = 0; i < 60; i++) {
  await new Promise(r => setTimeout(r, 2000));
  const data = await fetch(`/api/uploads/${uploadId}`).then(r => r.json());
  if (data.mediaId && data.status !== 'waiting') {
    mediaId = data.mediaId;
    break;
  }
}

// 4. Get the playback ID and render the player
const { playbackId } = await fetch(`/api/assets/${mediaId}`).then(r => r.json());

Option B: Copy the React components

Copy these ready-made components into your Next.js or React project:

<Uploader /> - drag-and-drop file upload with a progress bar:

import Uploader from '@/components/Uploader';

<Uploader />

<Player /> - FastPix HLS player web component:

import Player from '@/components/Player';

<Player playbackId="your-playback-id" />

<Recorder /> - in-browser screen and camera recorder:

import Recorder from '@/components/Recorder';

<Recorder />

Install the required dependencies:

npm install @fastpix/fp-player swr fix-webm-duration

Option C: Use the FastPix Node SDK directly

For non-Next.js backends, use the FastPix Node SDK without any of the StreamGate files:

npm install @fastpix/fastpix-node
import { Fastpix } from '@fastpix/fastpix-node';

const fp = new Fastpix({
  security: {
    username: process.env.FASTPIX_ACCESS_TOKEN_ID,
    password: process.env.FASTPIX_SECRET_KEY,
  },
});

const result = await fp.inputVideo.upload({
  corsOrigin: '*',
  pushMediaSettings: {
    accessPolicy: 'public',
    maxResolution: '1080p'
  },
});

console.log(result.data.uploadId, result.data.url);

For the full SDK reference, see the FastPix API reference.


Webhooks

StreamGate verifies incoming FastPix webhook payloads using HMAC-SHA256. To enable verification, set the FASTPIX_WEBHOOK_SECRET environment variable.

Register your endpoint

In the FastPix Dashboard, go to Manage → Webhooks and add:

https://your-domain.com/api/webhooks/fastpix

Supported events

EventDescription
video.media.createdFastPix has accepted the uploaded file
video.media.readyThe media has been processed and is ready to stream
video.media.failedProcessing failed

Note: If FASTPIX_WEBHOOK_SECRET is not set, signature verification is skipped. This is acceptable for local development but not recommended in production.


Error handling

All API routes return JSON error responses with an error field and an HTTP status code.

Status codeCause
401Webhook signature verification failed
500FastPix API error or unexpected server failure

Example: handling an upload error

const res = await fetch('/api/uploads', { method: 'POST' });

if (!res.ok) {
  const { error } = await res.json();
  console.error('Upload failed:', error);
}

FastPix API errors are logged to the server console with the full status code, response body, and headers.


Deploy to Cloudflare Pages

Cloudflare Pages is the recommended deployment target for StreamGate.

Install the adapter and Wrangler CLI

npm install --save-dev @cloudflare/next-on-pages wrangler

Create wrangler.toml

In the project root, create a wrangler.toml file with the following content:

name = "streamgate"
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".vercel/output/static"

NOTE:

The nodejs_compat flag is required. StreamGate uses the FastPix SDK and the Node.js crypto module for webhook signature verification.

Add build scripts to package.json

"scripts": {
  "pages:build": "npx @cloudflare/next-on-pages",
  "pages:deploy": "npm run pages:build && wrangler pages deploy"
}

Deploy

npm run pages:deploy

Set environment variables

  1. Open the Cloudflare Dashboard.
  2. Go to Pages → your project → Settings → Environment variables.
  3. Add all four environment variables for both the Production and Preview environments.
  4. Set NEXT_PUBLIC_BASE_URL to your production domain, for example https://streamgate.pages.dev.

Environment variables reference

VariableRequiredDescription
FASTPIX_ACCESS_TOKEN_IDYesBasic Auth username for the FastPix API
FASTPIX_SECRET_KEYYesBasic Auth password for the FastPix API
FASTPIX_WEBHOOK_SECRETNoHMAC-SHA256 key for verifying webhook payloads
NEXT_PUBLIC_BASE_URLNoBase URL for shareable links. Defaults to http://localhost:3000

What's next