Skip to content

satsdisco/videorelay

Repository files navigation

VideoRelay

VideoRelay

A decentralized video platform built on Nostr.

Browse, watch, upload, and zap videos β€” no accounts, no algorithms, no gatekeepers.

Live License Built on Nostr NIP-71

β†’ Try it at videorelay.lol


What is VideoRelay?

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.

Features

🎬 Discovery

  • 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)

πŸ“Ί Playback

  • 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)

⚑ Creator Tools

  • 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)

πŸ’Έ Monetization

  • Zap creators directly via Lightning (NIP-57)
  • WebLN-native with bolt11 invoice fallback
  • Zap amounts displayed on video cards

πŸ‘€ Social

  • Follow/unfollow creators (NIP-02 contact lists)
  • Comments on videos (NIP-22)
  • Channel pages with banner, bio, and video grid
  • Profile resolution from relays

βš™οΈ Power User

  • 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

Tech Stack

Layer Technology
Framework React + TypeScript
Build Vite
Styling Tailwind CSS + shadcn/ui
Nostr nostr-tools
Video HTML5 + HLS.js (lazy-loaded)
Hosting Vercel

Nostr Protocol Support

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)

Getting Started

Prerequisites

  • Node.js 18+
  • A NIP-07 Nostr browser extension (for signing/uploading)

Run locally

git clone https://github.com/satsdisco/videorelay.git
cd videorelay
npm install
npm run dev

Open http://localhost:8080.

Sign in

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

Deploy

npm run build
# Deploy dist/ to any static host, or use Vercel:
vercel --prod

Add a vercel.json SPA rewrite rule (already included in this repo).

Architecture

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

Engagement Scoring

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.

Contributing

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.

  1. Fork the repo
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Commit your changes
  4. Open a PR

License

MIT β€” do whatever you want with it.


Built on Nostr Β· Powered by Lightning Β· Hosted on Vercel

videorelay.lol

About

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors