A Next.js application for discovering, organizing, and streaming music from podcast feeds with Value4Value (V4V) Lightning Network integration.
Stablekraft extracts music tracks from podcast RSS feeds, manages them in a database, and provides playlist functionality with Bitcoin Lightning Network payments to artists.
- Next.js 15 with App Router
- TypeScript
- Prisma with PostgreSQL
- PWA with caching
- Nostr for authentication and social features
- WebLN/LNURL for Lightning payments
app/
├── page.tsx # Homepage with album discovery
├── album/[id]/ # Album detail pages
├── publisher/[id]/ # Publisher pages (official + matched albums)
├── playlist/ # Curated playlist views
├── music-tracks/ # Track browsing
├── favorites/ # User favorites (albums/tracks)
├── search/ # Fuzzy search with typo tolerance
├── library/ # User library
├── radio/ # Radio mode
├── sandbox/ # Development sandboxes
├── test-amber/ # NIP-46 remote signer testing
├── admin/ # Admin panel (Nostr auth)
├── settings/ # User settings
└── api/ # API routes
lib/
├── lightning/ # Lightning Network integration
│ ├── webln.ts # WebLN provider
│ ├── lnurl.ts # LNURL support
│ └── value-splits.ts # V4V payment splits
├── nostr/ # Nostr integration
│ ├── signer.ts # NIP-07/NIP-46/NIP-55 signing
│ ├── favorites.ts # Favorites sync to Nostr
│ ├── publish-queue.ts # Debounced Nostr event publishing
│ ├── playlist-events.ts # Kind 34139 playlist publishing
│ ├── relay.ts # Relay connection management
│ ├── zaps.ts # Zap support
│ └── nip05.ts # NIP-05 verification
├── playlist/ # Playlist configuration & resolution
│ ├── configs.ts # Playlist definitions
│ ├── parser.ts # XML feed parsing
│ ├── resolver.ts # Remote item resolution
│ └── handler.ts # API route handler factory
├── music-track-parser/ # Track extraction from feeds
├── rss-parser/ # RSS feed parsing
├── feed-parsing.ts # Feed import & track parsing
├── feed-discovery.ts # Automated feed discovery from playlists
├── v4v-resolver.ts # Value4Value resolution
├── fuzzy-search.ts # pg_trgm fuzzy matching
├── podcast-index-api.ts # Podcast Index API client
└── feed-cache.ts # Feed caching
components/
├── AdminPanel.tsx # Feed management interface
├── NowPlayingBar.tsx # Audio player controls
├── AlbumCard.tsx # Album display cards
├── GlobalBoostModal.tsx # Lightning boost payments
├── CDNImage.tsx # Optimized image loading
├── favorites/ # Favorite/sync/playlist publish buttons
└── Nostr/ # Nostr auth & social components
- Album and track browsing with artwork
- Publisher pages showing official releases and artist-matched albums
- Curated playlists (HGH, ITDV, IAM, MMM, etc.)
- Fuzzy search with typo tolerance (pg_trgm)
- Automated feed discovery: Automatically discovers and adds new feeds from playlists using Podcast Index API
- Streaming audio player
- iOS lockscreen/media controls support
- Shuffle and repeat modes
- Background playback
- Lightning Network boosts to artists
- WebLN wallet integration
- LNURL-pay support
- Payment splits per podcast:value spec
- Keysend discovery: Automatically discovers keysend fallback from Lightning Addresses for Helipad metadata support
- Nostr musician tagging: Resolves Nostr pubkeys from Lightning Address NIP-05 verification for tagging musicians in boost posts
- Favorites sync to Nostr (NIP-38 lists)
- NIP-07 (browser extension), NIP-46 (remote signer), NIP-55 (Android)
- Zap support
- Anonymous session-based favorites (no account required)
- Sync favorites to Nostr when logged in
- Favorite tracks and albums
- Persistent storage in database
# Database
DATABASE_URL="postgresql://..."
# Podcast Index API
PODCAST_INDEX_API_KEY="your_key"
PODCAST_INDEX_API_SECRET="your_secret"
# Admin Access (Nostr npubs)
ADMIN_NPUBS="npub1...,npub2..."
# Base URL
NEXT_PUBLIC_BASE_URL="https://yourdomain.com"
# Optional: Nostr
NEXT_PUBLIC_NOSTR_ENABLED="true"
NEXT_PUBLIC_NOSTR_RELAYS="wss://relay1.com,wss://relay2.com"npm install
npm run devnpx prisma generate
npx prisma db pushnpm run build
npm startGET/POST/PUT/DELETE /api/feeds- Feed CRUD operations
GET /api/albums-fast- Album listing with cachingGET /api/albums/[slug]- Album detailsGET /api/music-tracks- Track queries
GET/POST /api/favorites/tracks- Track favoritesGET/POST /api/favorites/albums- Album favoritesPOST /api/favorites/check- Check favorite status
GET /api/search- Fuzzy search across tracks/albums/artists
GET /api/playlist/[id]- Playlist dataGET /api/playlist/parse-feeds- Import tracks from playlist feeds
Configured for Vercel/Railway with:
- Automatic database migrations
- Environment variable management
- PWA manifest generation
This app consumes playlist feeds generated by a separate repository:
- Playlist Generator: musicL-playlist-updater
- Feed Output: chadf-musicl-playlists
Playlists are synced daily at 2 AM UTC via GitHub Actions.
MIT License - see LICENSE for details.