How OpenLoom Works
Under the Hood
The Architecture
Three independent layers. You own the first two. The third is replaceable.
Your Browser, Your Rules
The OpenLoom Chrome extension runs entirely in your browser. During setup, you connect your Supabase project by pasting your project URL and access token. The extension stores your backend credentials in Chrome's local storage, sandboxed to the extension. These credentials never leave your browser. (Convex and Firebase support coming soon.)
Nothing is uploaded until you explicitly choose to share a recording. When you do, the extension encodes the video and uploads it directly to your Supabase storage — authenticated by the credentials that only your browser has.
settings
├── provider: "supabase" # Backend provider
├── supabaseProjectUrl: "https://…"# Your Supabase project URL
├── supabaseServiceRoleKey: "…" # Service role key
│ # ⚠ NEVER uploaded. NEVER shared.
├── supabaseProjectRef: "…" # Project reference ID
└── provisioned: true # Backend setup complete
IndexedDB (openloom-blobs)
└── recording-blob # Temp recording before upload
# Cleaned up after shareYour backend credentials are the crown jewel. They grant write access to your backend project. Because they live only on your machine, no one else — not even OpenLoom's infrastructure — can modify your recordings, delete your data, or access your storage directly.
Inside Your Backend Project
OpenLoom currently uses Supabase as its backend. It stores video files, metadata, and reactions using Supabase's native services. Convex and Firebase support are coming soon.
Supabase Storage
Holds the actual video files in a public videos bucket. Videos are stored as single WebM or MP4 files with permanent public URLs — no signed tokens needed for playback.
storage/videos/
{short-code}.webm (12.4 MB)
{short-code}.mp4 (14.1 MB)
Public URL:
{project-url}/storage/v1/
object/public/videos/{code}.webmPostgreSQL Database
Two tables store video metadata and reactions. Accessed via PostgREST (from the extension) and Edge Functions (from the viewer). Row Level Security policies protect all data.
videos (table)
├── short_code: "a1b2c3d4"
├── title: "Q3 Product Demo"
├── storage_url: "https://..."
├── view_count: 142
├── duration_ms: 45200
└── capture_mode: "window"
reactions (table)
├── video_short_code: "a1b2c3d4"
├── emoji: "🔥"
└── timestamp: 12.5Edge Functions
Public GatewayA single Deno-based Edge Function openloom serves as the public API. It uses built-in SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY environment variables — no manual secrets configuration needed.
Deployed automatically by the Chrome extension during setup via the Supabase Management API.
Row Level Security
FirewallBoth tables have RLS enabled. Only the service role (used by Edge Functions and the Chrome extension) can read and write data. Direct public access is denied.
ALTER TABLE videos ENABLE ROW LEVEL SECURITY;
ALTER TABLE reactions ENABLE ROW LEVEL SECURITY;
-- Only service role has access
CREATE POLICY "service_role_access" ON videos
FOR ALL USING (true) WITH CHECK (true);The Public API Surface
Each backend exposes a public API through its serverless function layer. These are the only way anyone — including the official viewer — can interact with your recordings. No backdoors, no admin panels, no hidden routes.
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /v?code={code} | Fetch video metadata — title, duration, view count, capture mode |
| POST | /view | Increment the view counter. Fire-and-forget, no response body |
| GET | /reactions?code={code} | Fetch all timestamped emoji reactions for the video |
| POST | /reactions/add | Add a new emoji reaction at a specific timestamp |
Supabase uses query-parameter style URLs (/v?code=xxx). The web viewer automatically selects the correct URL pattern based on the provider prefix in the share link.
The Viewer is a Dumb Client
The OpenLoom web player at openloom.live is a completely stateless single-page application. It carries zero secrets and has zero special access. It's a static Next.js app exported and deployed on GitHub Pages — nothing more.
Zero backend credentials
Can't read databases or storage directly
Zero server-side logic
Static HTML/JS/CSS on GitHub Pages
Zero persistent state
No cookies, sessions, or user accounts
Zero write access
Only calls serverless functions over HTTPS
What happens when someone opens a link
https://openloom.live/v/{encoded-id}/{video-code}Decode the base64url ID to extract the provider prefix (s-, c-, or f-) and project identifier.
s → supabase.co/functions | c → convex.site | f → cloudfunctions.netThe provider prefix determines which URL pattern to use.
GET /v?code={code} → { title, duration_ms, view_count, storage_url, ... }Retrieve the video's metadata from the serverless function.
fetch(storage_url) → <video src={url} />The storage URL points directly to the video file. Supabase and Firebase use permanent public URLs. Convex uses a redirect proxy.
<video /> → Plyr initializes → reactions load in parallelVideo plays. Reactions load in parallel. View count increments.
The viewer does not know your admin credentials, your database schema, or your storage bucket name. It only knows the public serverless function URL — the same URL available to anyone with the link.
Deployed on GitHub Pages
The official web player at openloom.live is deployed as a static Next.js export on GitHub Pages. No server, no runtime, no build service — just static HTML/CSS/JS served from GitHub's CDN. This gives the viewer maximum transparency and zero operational complexity.
# The webviewer is a Next.js app with static export
# next.config.ts → output: "export"
# GitHub Actions workflow triggers on push to main:
1. Checkout repo → Install dependencies
2. next build → generates static /out directory
3. Upload /out as GitHub Pages artifact
4. Deploy to GitHub Pages environment
# Result: static files served at openloom.live
# Custom domain configured via CNAME record
# HTTPS provided automatically by GitHubFully auditable
Every deployment is a git commit. The source code, build output, and deployed version are all public and verifiable.
Zero cost
GitHub Pages is free for public repositories. No hosting bills, no usage-based pricing, no surprise charges.
No build server
GitHub Actions runs the build. No Netlify, Vercel, or Cloudflare account needed. One less vendor dependency.
Global CDN
GitHub Pages uses Fastly's CDN. Static files are served from edge locations worldwide with automatic HTTPS.
Deploy Your Own Viewer
Because the viewer is just a static web app with no built-in secrets, you can fork and deploy your own instance. This gives you full control and eliminates any dependency on openloom.live.
# 1. Fork the repository on GitHub
$ git clone https://github.com/your-fork/OpenLoom.git
$ cd OpenLoom/webviewer
# 2. Enable GitHub Pages in repo Settings → Pages
# Source: "GitHub Actions"
# 3. Push to main — GitHub Actions builds & deploys automatically
$ git push origin main
# 4. (Optional) Add a custom domain in Settings → Pages
# watch.yourcompany.com → CNAME to your-fork.github.ioYour own domain
watch.yourcompany.com instead of openloom.live
Custom branding
Modify the CSS, swap colors, add your logo
Full UI control
Change the player, add features, remove what you don't need
Zero downtime risk
Even if openloom.live goes offline, your recordings are accessible
This is the key insight: your data lives on your backend. Your viewer can live anywhere. The two are connected only by public HTTPS endpoints. Swap the viewer, swap the backend — nothing about the other layer changes.
Own your recordings
No middleman. No vendor lock-in. Your backend, your machine, your rules.