VidStr - Decentralized Video Platform

VidStr is a decentralized, censorship-resistant video sharing platform built on the Nostr protocol. It enables users to upload, share, and discover videos without central authority control. Videos are stored on Blossom servers with metadata distributed across multiple Nostr relays.

Technical Overview

Protocol
Nostr (Notes and Other Stuff Transmitted by Relays)
Architecture
Client-side only, no backend server required. Pure static site with WebSocket connections to Nostr relays.
Storage
Videos: Blossom decentralized file servers. Metadata: Distributed across Nostr relay network. Local: Browser IndexedDB.
Identity
Nostr cryptographic keypair (secp256k1). Public key (npub) is your identity. Private key (nsec) signs your content.

Nostr Protocol Support (NIPs)

  • NIP-01: Basic protocol flow, event signing and verification
  • NIP-04: Encrypted Direct Messages (legacy AES-256-CBC)
  • NIP-05: DNS-based identity verification
  • NIP-07: Browser extension signers (Alby, nos2x, Flamingo)
  • NIP-17: Private Direct Messages with gift-wrapping (metadata protection)
  • NIP-19: Bech32-encoded identifiers (npub, note, naddr, nevent, nprofile)
  • NIP-25: Reactions (like/dislike/emoji on videos)
  • NIP-36: Content warnings for sensitive material
  • NIP-50: Full-text search via specialized relays
  • NIP-51: Lists and playlists (kind 30005 video collections)
  • NIP-57: Lightning zaps (Bitcoin micropayments to creators)
  • NIP-65: Relay list metadata (user-configurable relay preferences)
  • NIP-71: Video events (kinds 21, 22, 34235, 34236)
  • NIP-92: Media attachments with imeta tags
  • NIP-94: File metadata specifications
  • NIP-96: File storage server authentication

Video Event Kinds (NIP-71)

Kind 21: Regular Horizontal Video

Type
Regular Event (immutable)
Orientation
Horizontal/Landscape
Editable
No
Format
Uses imeta tags for video metadata
Use Case
Standard YouTube-style videos, tutorials, movies

Kind 22: Regular Vertical Video

Type
Regular Event (immutable)
Orientation
Vertical/Portrait
Editable
No
Format
Uses imeta tags for video metadata
Use Case
TikTok/Instagram Reels style shorts, stories

Kind 34235: Addressable Horizontal Video

Type
Addressable Event (replaceable)
Orientation
Horizontal/Landscape
Editable
Yes (publish new event with same d tag)
Format
Uses imeta tags plus d tag identifier
Use Case
Videos that may need metadata corrections, URL migrations, or updates

Kind 34236: Addressable Vertical Video

Type
Addressable Event (replaceable)
Orientation
Vertical/Portrait
Editable
Yes (publish new event with same d tag)
Format
Uses imeta tags plus d tag identifier
Use Case
Editable short-form videos

Legacy Format Support

VidStr maintains backwards compatibility with older NIP-71 video events that use separate url/m/x/dim/thumb tags instead of imeta. These legacy events are automatically detected and parsed correctly, ensuring all historical content remains accessible.

Multi-Relay Architecture

Default Relay Configuration (9 relays)

  1. wss://relay.damus.io - General purpose, high availability relay
  2. wss://nos.lol - Community-focused relay
  3. wss://relay.primal.net - Primal's infrastructure relay
  4. wss://relay.snort.social - Snort's relay network
  5. wss://relay.ditto.pub - Media-focused relay for content
  6. wss://nostr.wine - Content distribution relay
  7. wss://nostr.mom - Community relay
  8. wss://relay.mostr.pub - Bridge relay (Mastodon integration)
  9. wss://nostr21.com - Bitcoin-focused relay

Search Relays (NIP-50)

  • wss://search.nos.today - Full-text search support
  • wss://relay.noswhere.com - Full-text search support

Query Strategy

Read Strategy
Query ALL read-enabled relays in parallel. Each relay returns up to 100 events. Results are deduplicated by event ID and sorted chronologically. Top 20 most recent displayed per page.
Write Strategy
Publish to ALL write-enabled relays simultaneously. Ensures maximum distribution and redundancy across the network.
Timeout
5 seconds per relay to prevent slow relays from blocking UI
Benefits
Maximum content discovery, redundancy, censorship resistance
Trade-offs
Increased bandwidth usage, slightly longer initial load times

User Configuration

Users can customize their relay list in Settings. Add/remove relays and toggle read/write permissions per relay. When logged in, relay configuration is published as NIP-65 event (kind 10002) and synced across devices.

Core Features

Video Upload

  • Upload with Nostr account or anonymously
  • Anonymous uploads generate ephemeral keypair (displayed once)
  • Files uploaded to Blossom servers with NIP-96 authentication
  • Metadata published as Nostr events to configured relays
  • Support for all video formats (browser-dependent)
  • Optional thumbnail upload
  • Hashtag tagging for categorization
  • Content warnings for sensitive material
  • Choose regular (immutable) or addressable (editable) format
  • File cloning prevents permission errors on mobile devices

Playlists (NIP-51)

  • Create video collections using kind 30005 events
  • Support for all video kinds: 21, 22, 34235, 34236
  • Reference regular videos with e tags, addressable with a tags
  • Add titles, descriptions, and cover images
  • Edit and delete playlists (addressable events)
  • Browse global playlists or from followed users
  • Add videos to multiple playlists

Reactions (NIP-25)

  • Kind 7 reaction events
  • Like (+), dislike (-), custom emoji
  • Custom text reactions (max 20 characters)
  • Toggle reactions on/off
  • Real-time reaction counts
  • References video with e tag (regular) or a tag (addressable)

Comments

  • Kind 1 reply events with e and p tags
  • Nested reply support
  • Real-time updates
  • Rich text with URLs and Nostr mentions
  • Comment on any video

Direct Messages

  • NIP-04: Legacy encrypted DMs (AES-256-CBC, metadata visible)
  • NIP-17: Modern gift-wrapped DMs (XChaCha20, metadata protected)
  • End-to-end encryption with NIP-44
  • File attachments via Blossom
  • Real-time message delivery
  • Conversation management

Search & Discovery

  • Full-text search via NIP-50 relays
  • Hashtag browsing (#tag URLs)
  • Global feed (all videos from all relays)
  • Following feed (videos from followed users)
  • Profile pages with all user videos
  • Related video suggestions
  • Client-side filtering fallback for non-NIP-50 relays

Lightning Zaps (NIP-57)

  • Send Bitcoin micropayments to video creators
  • Send zaps to user profiles
  • WebLN browser wallet integration
  • Nostr Wallet Connect (NWC) support
  • LNURL invoice generation
  • QR code display for mobile wallets
  • Zap receipts (kind 9735) for verification
  • Display total sats received per video
  • Requires lud16 or lud06 in profile metadata

User Profiles

  • Kind 0 metadata events
  • Display name, bio, avatar, banner
  • Website links and social verification (NIP-05)
  • Lightning address display (lud16/lud06)
  • Video gallery view
  • Follow/unfollow functionality
  • Editable by profile owner

How VidStr Works

Step 1: Identity & Authentication

Users authenticate with a Nostr keypair. Three options available:

  1. Generate New Keys: Create fresh keypair in browser. Keys stored in IndexedDB or extension.
  2. Browser Extension: Use Alby, nos2x, Flamingo, or other NIP-07 signers. Most secure option.
  3. Import Existing Keys: Import nsec or hex private key from another client.
  4. Anonymous Mode: Generate ephemeral keypair per upload. Keys shown once after upload.

No email, no password, no central account database. Your keypair is your identity across the entire Nostr ecosystem.

Step 2: Video Upload Process

  1. User selects video file from device
  2. File immediately cloned to memory (prevents permission errors)
  3. Video dimensions detected to determine orientation
  4. User adds metadata: title, description, hashtags, thumbnail
  5. File uploaded to Blossom server (https://blossom.primal.net/)
  6. Upload authenticated with Nostr signature (NIP-96)
  7. Server returns URL, SHA-256 hash, mime type, dimensions
  8. Nostr event created with imeta tags containing all metadata
  9. Event signed with user's private key
  10. Event published to all write-enabled relays
  11. Event ID returned, video now discoverable network-wide

Step 3: Video Discovery

Global Feed

  1. Client queries all read-enabled relays in parallel
  2. Filter: kinds [21, 22, 34235, 34236], limit 100, until current_time
  3. Each relay returns up to 100 most recent video events
  4. Events deduplicated by event ID (same video from multiple relays)
  5. Events sorted by created_at timestamp (newest first)
  6. Top 20 displayed to user
  7. Infinite scroll loads next page with until=oldest_displayed_timestamp

Search

  1. Query sent to NIP-50 search relays with search parameter
  2. Also query regular relays as fallback
  3. Client-side filtering for non-NIP-50 relays
  4. Results combined and deduplicated
  5. Matches on title, description, or hashtags

Following Feed

  1. Fetch user's kind 3 follow list event
  2. Extract pubkeys from p tags
  3. Query videos with authors filter
  4. Display chronologically

Step 4: Video Playback

  1. User clicks video thumbnail
  2. Navigate to video page with event ID or naddr
  3. Fetch video event from relays
  4. Parse imeta tags or legacy url tags
  5. Load video URL in HTML5 video player
  6. Display metadata: title, description, creator profile
  7. Load reactions, comments, zap count from relays
  8. Enable user interactions (react, comment, zap, share)

Step 5: User Interactions

Reactions

  • Create kind 7 event with content: "+", "-", or emoji
  • Add e tag (for regular videos) or a tag (for addressable videos)
  • Add p tag with video author pubkey
  • Sign and publish to write-enabled relays

Comments

  • Create kind 1 event with comment text in content
  • Add e tag referencing video event ID (root)
  • Add e tag for reply-to comment (if replying to comment)
  • Add p tags for video author and comment author
  • Sign and publish

Zaps

  • Fetch creator's lud16 or lud06 from profile metadata
  • Generate LNURL invoice via creator's lightning service
  • Display invoice as QR code and copyable text
  • Pay via WebLN (browser extension) or external wallet
  • Zap receipt (kind 9735) published by recipient's lightning service
  • Receipt references original video event

File Storage (Blossom Protocol)

Protocol
Blossom - Decentralized file hosting with Nostr authentication
Authentication
NIP-96 style event signatures. Sign upload request with Nostr keys.
Content Addressing
Files identified by SHA-256 hash. Same file = same URL across all servers.
Metadata
Stored in imeta tags: url, hash (x), mime type (m), dimensions (dim), duration, bitrate, image (thumbnail)
Fallbacks
Multiple server URLs can be specified for redundancy
Server Used
https://blossom.primal.net/ (default)

Security & Privacy

Encryption

Event Signing
Schnorr signatures on secp256k1 curve. All events cryptographically signed and verified.
Direct Messages (NIP-04)
AES-256-CBC encryption. Legacy format with visible metadata (sender, recipient, timestamp).
Direct Messages (NIP-17)
XChaCha20-Poly1305 encryption (NIP-44). Gift-wrapped to hide all metadata. Only recipient can decrypt.
File Integrity
SHA-256 hashing ensures files cannot be tampered with. Hash stored in event metadata.

Privacy Features

  • No Central Server: VidStr is pure client-side. No tracking, no analytics.
  • Anonymous Posting: Upload without account using ephemeral keys.
  • Local Storage Only: All data in browser IndexedDB. Never sent to central server.
  • Keys Never Shared: Private keys stay on your device or extension.
  • Relay Privacy: Individual relay operators can see IP addresses and event metadata.
  • Encrypted DMs: End-to-end encryption ensures only sender and recipient can read.
  • No KYC: No email, phone number, or identity verification required.

Technology Stack

Frontend Technologies

Framework
React 18.x with TypeScript
Routing
React Router v6 with BrowserRouter
Styling
TailwindCSS 3.x utility-first CSS
Components
shadcn/ui (Radix UI primitives with Tailwind styling). 48+ accessible components.
State Management
TanStack Query for server state. React Context for global state.
Build Tool
Vite for fast development and optimized production builds

Nostr Integration

Core Library
Nostrify - Modern Nostr framework for web and Deno
React Integration
@nostrify/react - React hooks and context providers
Authentication
@nostrify/react/login - Multi-account management
Utilities
nostr-tools v2.13+ - NIP-19 encoding, event creation, signature verification

Lightning Payment Integration

WebLN
@webbtc/webln-types - Browser extension wallet interface
NWC
@getalby/sdk - Nostr Wallet Connect for remote wallet control
QR Codes
qrcode library - Generate Lightning invoice QR codes

Data Storage

Local Database
IndexedDB via idb library - Stores accounts, settings, cached events
Encrypted Messages
Custom encrypted message store for NIP-04 and NIP-17 DMs
Configuration
localStorage for theme, relay list, and app preferences

Deployment & Hosting

Type
Static site (no server-side code)
Build Output
HTML, CSS, JavaScript, and static assets in /dist directory
Hosting Requirements
Any static file host. HTTPS required for WebSocket connections.
CDN Compatible
Yes, works with Cloudflare, Netlify, Vercel, etc.
No Backend Needed
All logic runs in browser. Direct WebSocket connections to Nostr relays.
Current Deployment
https://vidstr.shakespeare.wtf

API Reference (Nostr Protocol)

VidStr has no traditional REST API. All communication uses the Nostr protocol over WebSockets.

Query Videos

REQ <subscription-id>
{
  "kinds": [21, 22, 34235, 34236],
  "limit": 100,
  "until": <unix-timestamp>
}
            

Publish Video

EVENT {
  "kind": 21,
  "content": "Video description",
  "tags": [
    ["imeta",
      "url https://blossom.server/file.mp4",
      "m video/mp4",
      "dim 1920x1080",
      "x <sha256-hash>",
      "image https://blossom.server/thumb.jpg",
      "duration 120.5"
    ],
    ["title", "Video Title"],
    ["published_at", "<unix-timestamp>"],
    ["t", "hashtag"],
    ["alt", "Accessibility description"]
  ],
  "created_at": <unix-timestamp>,
  "pubkey": "<author-public-key>",
  "id": "<event-id>",
  "sig": "<signature>"
}
            

React to Video

EVENT {
  "kind": 7,
  "content": "+",
  "tags": [
    ["e", "<video-event-id>"],
    ["p", "<video-author-pubkey>"],
    ["k", "<video-kind>"]
  ],
  "created_at": <unix-timestamp>,
  "pubkey": "<reactor-public-key>",
  "id": "<event-id>",
  "sig": "<signature>"
}
            

Known Limitations

  • Relay Dependency: Content availability depends on relay uptime and retention policies
  • No Global Moderation: Decentralized nature means no platform-wide content moderation
  • Relay Policies: Individual relays may filter or block certain content
  • File Size Limits: Blossom servers may have upload size restrictions
  • Bandwidth Usage: Querying 10 relays simultaneously increases data usage
  • Browser Storage: IndexedDB quota limitations vary by browser
  • Discovery: New relays or content may take time to propagate
  • Key Management: Lost private keys cannot be recovered

Getting Started Guide

For Users

  1. Visit https://vidstr.shakespeare.wtf
  2. Click "Log in" or "Sign up" to create/connect Nostr identity
  3. Optional: Configure relays in Settings (default relays work fine)
  4. Click "Upload" button to share your first video
  5. Browse global feed or search for content
  6. Follow creators, react to videos, leave comments
  7. Zap sats to support creators you enjoy

For Developers

  1. Click "Edit with Shakespeare" badge to fork the project
  2. Modify code in Shakespeare IDE (AI-assisted development)
  3. Add custom features or integrate with your services
  4. Deploy to your own domain
  5. Connect to your own relays
  6. Customize branding and UI

Troubleshooting

Q: Videos not loading?
A: Check relay connections in Settings > Relays. Try adding more relays. Some may be offline or rate-limiting. Verify you have at least 1 read-enabled relay.
Q: Can't upload videos?
A: Ensure logged in (unless anonymous). Check Blossom server accessibility. Try different browser if permission errors occur. Verify you have at least 1 write-enabled relay.
Q: Upload fails with "permission" error?
A: This is a browser file access issue. VidStr now clones files to memory immediately. Try: 1) Refresh page, 2) Use different browser, 3) Check browser permissions, 4) Try smaller file.
Q: Search not working?
A: Enable NIP-50 search relays (wss://search.nos.today, wss://relay.noswhere.com) in Settings. Regular relays don't support full-text search.
Q: Lost my keys?
A: Private keys cannot be recovered. No password reset exists in decentralized system. Always back up nsec securely. For anonymous posts, keys shown once after upload.
Q: Zaps not working?
A: Ensure recipient has lightning address (lud16 or lud06 in profile). Connect WebLN wallet or configure NWC. Check wallet has funds and connection.
Q: Videos from days ago missing in feed?
A: This is due to multi-relay query behavior. Each relay returns its 100 most recent videos. If some relays lack recent content, you may see time gaps. Increase relays or adjust query strategy in code.
Q: Can I delete a video?
A: You can publish kind 5 deletion request, but relays are not required to honor it. Addressable events (34235/34236) can be "edited" to empty content. Regular events (21/22) are immutable.

Project Metadata

Name
VidStr
Version
2026.02.02.2
Release Date
2026-02-02
License
MIT Open Source
Repository
nostr://npub14rg4vrt2v374q95ezeeydu3hkdhmzglcj950mggacap4x0lv0gyq04wun7/git.shakespeare.diy/vidstr
Deployment URL
https://vidstr.shakespeare.wtf
Built With
Shakespeare.diy AI-powered development platform
Maintainer
stl1988 (npub14rg4vrt2v374q95ezeeydu3hkdhmzglcj950mggacap4x0lv0gyq04wun7)

Additional Resources

  • Nostr Protocol: https://nostr.com
  • NIPs Repository: https://github.com/nostr-protocol/nips
  • NIP-71 Video Events: https://github.com/nostr-protocol/nips/blob/master/71.md
  • Blossom Specification: https://github.com/hzrd149/blossom
  • Lightning Network: https://lightning.network
  • Nostrify Documentation: https://nostrify.dev
  • Shakespeare Builder: https://shakespeare.diy