A decentralized video platform built on Nostr.
Browse, watch, upload, and zap videos β no accounts, no algorithms, no gatekeepers.
VideoRelay is a YouTube-style frontend for the Nostr protocol. Video content is fetched directly from Nostr relays using NIP-71 video events. There's no central server, no platform that can ban you, and no algorithm deciding what you see.
Your identity is your keypair. Your feed is your relay selection. Creator support goes directly through Lightning with no middleman taking a cut.
- Home feed with trending, most-zapped, and following views
- Category filters β Bitcoin, Lightning, Nostr, Privacy, and more
- Shorts β vertical scroll feed for short-form content (TikTok-style)
- Live streams via NIP-53
- Featured Creators section (curated via NIP-51, admin-controlled)
- Custom video player with HLS support
- Keyboard shortcuts, playback speed, PiP, fullscreen
- Blurred background for vertical videos
- Touch-optimized controls on mobile (tap to show/hide, double-tap to seek)
- Upload videos to Blossom decentralized storage
- Publish NIP-71 video events signed with your Nostr extension
- Tag as Short, add categories, custom thumbnails
- Configurable Blossom media server (default: blossom.primal.net)
- Zap creators directly via Lightning (NIP-57)
- WebLN-native with bolt11 invoice fallback
- Zap amounts displayed on video cards
- Follow/unfollow creators (NIP-02 contact lists)
- Comments on videos (NIP-22)
- Channel pages with banner, bio, and video grid
- Profile resolution from relays
- Relay manager β add, remove, toggle per-relay
- NSFW blur system β multi-layer detection with click-to-reveal
- Persistent auth across devices (pubkey saved in localStorage)
- Settings for playback, content preferences, and relay config
| Layer | Technology |
|---|---|
| Framework | React + TypeScript |
| Build | Vite |
| Styling | Tailwind CSS + shadcn/ui |
| Nostr | nostr-tools |
| Video | HTML5 + HLS.js (lazy-loaded) |
| Hosting | Vercel |
| NIP | Description |
|---|---|
| NIP-01 | Basic protocol |
| NIP-02 | Contact lists (following) |
| NIP-07 | Browser extension signing |
| NIP-19 | bech32 npub encoding |
| NIP-22 | Comments |
| NIP-36 | Sensitive content |
| NIP-51 | Lists (curated creators) |
| NIP-53 | Live activities |
| NIP-57 | Lightning zaps |
| NIP-71 | Video events |
| NIP-94 | File metadata |
| NIP-96 | File storage (Blossom) |
- Node.js 18+
- A NIP-07 Nostr browser extension (for signing/uploading)
git clone https://github.com/satsdisco/videorelay.git
cd videorelay
npm install
npm run devOpen http://localhost:8080.
VideoRelay uses NIP-07 for authentication β no passwords, no emails.
Recommended extensions:
- Alby β browser extension, also handles Lightning
- nos2x β lightweight, Firefox + Chrome
- Nostore β Safari on macOS/iOS
npm run build
# Deploy dist/ to any static host, or use Vercel:
vercel --prodAdd a vercel.json SPA rewrite rule (already included in this repo).
src/
βββ components/ # Reusable UI components
β βββ VideoCard # Thumbnail, title, zap count
β βββ VideoPlayer # Custom player with HLS support
β βββ MiniSidebar # Icon nav (collapsible to labels)
β βββ ...
βββ hooks/ # Data fetching + state
β βββ useNostrVideos # Parallel relay querying
β βββ usePopularVideos # Engagement-scored discovery
β βββ useNostrAuth # NIP-07 session management
β βββ ...
βββ lib/ # Core logic
β βββ nostr.ts # Relay pool, NIP-71 parsing
β βββ videoDiscovery.ts # Trending + engagement scoring
β βββ posterCache.ts # Offscreen poster extraction
β βββ blossom.ts # File upload with NIP-98 auth
β βββ nsfw.ts # Multi-layer content detection
β βββ safeStorage.ts # localStorage quota management
βββ pages/ # Route-level components
βββ Index # Home feed
βββ Watch # Video player page
βββ Channel # Creator profile
βββ Shorts # Vertical scroll feed
βββ Upload # Publish a video
βββ Settings # Relays, playback, content prefs
VideoRelay ranks content using an engagement score with time decay:
score = (zapAmount + zapCountΓ100 + reactionsΓ10 + repostsΓ50 - dislikesΓ200)
Γ timeDecay(hours)
Where timeDecay = 1 / (1 + hours/24)^0.5 β content doesn't permanently lose rank, but fresh content gets a boost.
Issues and PRs welcome. This is a public good project β if you're building on Nostr video, feel free to fork, extend, or take pieces for your own client.
- Fork the repo
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes
- Open a PR
MIT β do whatever you want with it.