How Content Lives on Nostr
How pleb.school uses Nostr for content
pleb.school publishes course and lesson content to Nostr and keeps operational metadata in PostgreSQL. The UI merges both sources into a single, consistent view.
Event kinds used
- NIP-23 (kind 30023): free resources (long-form)
- NIP-99 (kind 30402): paid resources (classified listings with price hint)
- NIP-51 (kind 30004): courses (lists of lessons)
- NIP-57 (kind 9735): zap receipts
- NIP-01 (kind 0): profiles
Example: free resource (NIP-23)
{ "kind": 30023, "tags": [["d","lesson-id"],["title","Lesson title"],["summary","..."]] }
Example: paid resource (NIP-99)
{ "kind": 30402, "tags": [["d","lesson-id"],["title","Premium lesson"],["price","10000","sats"]] }
Example: course (NIP-51)
{ "kind": 30004, "tags": [["d","course-id"],["name","Course title"],["a","30023:pubkey:lesson-id"]] }
Why the database still matters
- The database stores the authoritative price and ownership
- Each published event is linked via a noteId
- The UI merges DB metadata with Nostr content for display and access checks
Publishing flow (high level)
Draft in DB -> create event -> sign (NIP-07 or server-side) -> publish to relays -> store noteId
Publishing to Nostr makes content portable and verifiable, while pleb.school enforces access to paid content based on database purchases and zap receipts.