# Nostr Music > A decentralized music platform built on the Nostr protocol. Users can upload, discover, and share music tracks and playlists — without gatekeepers or censorship. Audio files are stored on Blossom servers (decentralized CDN). Metadata and social interactions are published as Nostr events. The app runs entirely in the browser with no central backend. ## Overview Nostr Music is a React single-page application (SPA) deployed at https://nostr-music.shakespeare.wtf. It uses: - **Nostr** for decentralized identity, metadata, social interactions, and content discovery - **Blossom** (NIP-96/BUD-01) for decentralized audio and image file storage - **Lightning Network** (via NIP-57 zaps and Nostr Wallet Connect) for micropayments - **NIP-65** relay management so users connect to their own preferred relays Users do not need an account — anonymous uploads are supported using an ephemeral generated keypair. Logged-in users authenticate via NIP-07 browser extensions (e.g. Alby, nos2x), nsec paste, or NIP-46 remote bunkers. ## Custom Nostr Event Kinds This app uses the following custom and standard Nostr event kinds: - **Kind 36787** — Music Track (addressable, kind range 30000–39999). Contains audio file URL, title, artist, artwork, genre tags, license, and optional extended metadata. - **Kind 34139** — Playlist (addressable). Contains an ordered list of track references via `a` tags. - **Kind 10002** — NIP-65 Relay List. Read on login to connect to user's preferred relays. - **Kind 7** — NIP-25 Reactions (likes/dislikes on tracks and playlists). - **Kind 5** — NIP-09 Deletion events. - **Kind 9735** — NIP-57 Zap receipts for Lightning payments. Full custom NIP specification: [NIP.md](https://nostr-music.shakespeare.wtf/NIP.md) ## Tech Stack - **React 18** + **TypeScript** + **Vite** - **TailwindCSS 3** + **shadcn/ui** (Radix UI components) - **Nostrify** — Nostr protocol framework (NPool, NRelay1, BlossomUploader) - **TanStack Query** — data fetching and caching - **React Router v6** — client-side routing - **nostr-tools** — NIP-19 encoding/decoding, event signing utilities ## Key Pages & Routes - `/` — Main feed: latest tracks, playlists, radio mode - `/:npub` — User profile page (tracks, playlists, follow/unfollow, zap) - `/:naddr` — Track detail page (play, lyrics, metadata, comments, zaps) - `/settings` — Relay management (NIP-65), version info - `/changelog` — Full version history ## Key Source Files - [`src/version.ts`](https://nostr-music.shakespeare.wtf/src/version.ts): Current version number (YYYY.MM.DD.patch format) - [`src/hooks/useMusicTracks.ts`](https://nostr-music.shakespeare.wtf): MusicTrack type definition and query hooks - [`src/hooks/useAnonymousUpload.ts`](https://nostr-music.shakespeare.wtf): Anonymous and authenticated Blossom upload - [`src/hooks/useRadio.ts`](https://nostr-music.shakespeare.wtf): Radio mode shuffle queue with play-history tracking - [`src/components/music/AudioPlayer.tsx`](https://nostr-music.shakespeare.wtf): Bottom-bar audio player with seek, volume, radio skip controls - [`src/components/music/UploadTrackForm.tsx`](https://nostr-music.shakespeare.wtf): Full track upload form with progress dialog - [`src/components/NostrProvider.tsx`](https://nostr-music.shakespeare.wtf): NPool relay pool, routes reads to read-relays and writes to write-relays - [`src/components/NostrSync.tsx`](https://nostr-music.shakespeare.wtf): Fetches NIP-65 relay list immediately on login - [`src/lib/musicConstants.ts`](https://nostr-music.shakespeare.wtf): Event kind numbers and Blossom server list ## Music Track Event Schema (Kind 36787) ### Required tags - `d` — unique identifier - `title` — track title - `artist` — artist name - `url` — direct URL to audio file (MP3, FLAC, OGG, M4A) - `t` — must include at least `"music"` ### Optional tags - `image` — artwork URL - `video` — music video URL - `lyrics` — URL to SRT subtitle file - `album` — album name - `track_number` — position in album - `released` — ISO 8601 date - `license` — license name and optional URL (e.g. `["license", "CC BY 4.0", "https://..."]`) - `explicit` — `"true"` for explicit content - `ai_generated` — `"true"` for AI-generated content - `duration` — length in seconds - `format` — audio format (mp3, flac, m4a, ogg) - `bitrate` — e.g. `"320kbps"` - `sample_rate` — in Hz - `language` — ISO 639-1 code - `zap` — Lightning address for zap splits - `content-warning` — reason string - `alt` — NIP-31 human-readable description ### Content field May contain lyrics and/or production credits as plain text. ## Blossom Upload Files are uploaded to Blossom servers (tried sequentially for reliability): 1. `https://blossom.primal.net/` 2. `https://nostr.download/` 3. `https://cdn.satellite.earth/` 4. `https://blossom.oxtr.dev/` Upload requires a Blossom auth event signed by the user (or ephemeral key for anonymous uploads). The returned URL is stored in the `url` tag of the track event. ## Radio Mode The radio feature (`src/hooks/useRadio.ts`) plays all available tracks in a smart shuffle: - Fisher-Yates shuffle for unbiased randomization - Tracks marked as played; won't repeat until 80% of all tracks have played - Queue reshuffled when exhausted - 10-second timeout per track in radio mode — auto-skips broken/slow tracks - Audio errors also trigger auto-skip ## Relay Configuration Default relays (used before NIP-65 sync): - `wss://relay.ditto.pub` - `wss://relay.damus.io` - `wss://nos.lol` - `wss://relay.primal.net` - `wss://relay.mostr.pub` On login, the app immediately fetches the user's kind 10002 NIP-65 relay list and replaces the defaults. Users can also manage relays manually at `/settings`. ## Versioning Version format: `YYYY.MM.DD.patch` (e.g. `2026.02.02.6`). Updated manually in `src/version.ts` after each meaningful code change. ## Docs - [Changelog](https://nostr-music.shakespeare.wtf/changelog): Full version history - [NIP.md](https://nostr-music.shakespeare.wtf/NIP.md): Custom Nostr event schema specification ## Optional - [llmstxt.org](https://llmstxt.org): Specification for this file format - [Nostrify docs](https://nostrify.dev): Framework used for Nostr integration - [NIP-65](https://github.com/nostr-protocol/nips/blob/master/65.md): Relay List Metadata spec - [BUD-01](https://github.com/hzrd149/blossom/blob/master/buds/01.md): Blossom server spec