Magneto Directory is an operator-less, Nostr-native directory for content locators (BitTorrent magnets and IPFS CIDs). The client publishes signed Nostr events directly to relays. The backend only indexes and serves read-only queries.
- Board definitions (kind 30091) using parameterized replaceable events
- Listings (kind 30092) with magnet, I2P magnet, and IPFS locator tags
- Curator picks per board (kind 30093) for consensus curation
- Personal curated lists (kind 30094)
- Minimal UI (boards, board page with New/Curated, listing detail, submit listing, profile, new list)
- Read-only API routes
- Relay indexer with signature validation
- Next.js App Router + Route Handlers
- TypeScript
- Prisma + Postgres (Docker)
- nostr-tools v2
- Install dependencies
npm install- Start Postgres
docker-compose up -d- Configure env
cp .env.example .env- Run migrations
npx prisma migrate dev --name init- Run web + indexer
npm run dev
npm run indexer:devDATABASE_URLPostgres connection stringMAGNETO_RELAYScomma-separated relay URLs for indexerNEXT_PUBLIC_MAGNETO_RELAYScomma-separated relay URLs for client publishingINDEXER_SINCE_DAYSbackfill window (default 30)
npm run devstart Next.js dev servernpm run indexer:devbackfill + live indexernpm run indexer:rebuildwipe cache tables and reindexnpm run db:migratePrisma migrate devnpm run db:studioPrisma Studionpm run typecheckTypeScript type checknpm run testalias for typecheck
Kinds:
- 30091 Board Definition (parameterized replaceable)
- 30092 Listing
- 30093 Curator Picks (parameterized replaceable)
- 30094 Personal Curated List (parameterized replaceable)
Board definition tags:
d=magneto:<slug>name= display title- optional:
about,rules,t,r,visibility
Listing tags:
board=magneto:<slug>- locators:
magnet,i2p,ipfs(at least one) - optional:
title,summary,t
Curator picks tags:
d=magneto:picks:<board_slug>board=magneto:<slug>- repeated
etags with markerpick
Personal list tags:
d=magneto:list:<list_slug>namerequired- optional:
about - items:
boardtags,etags with markeritem
Validation helpers live in src/lib/nostr/schema.ts.
- Connects to configured relays
- Backfills
INDEXER_SINCE_DAYShistory, then stays live - Validates signatures and schema
- Writes derived records into Postgres
GET /api/boardsGET /api/boards/:slugGET /api/boards/:slug/newGET /api/boards/:slug/curatedGET /api/listings/:eventIdGET /api/listings/:eventId/thread(stub)GET /api/profiles/:npubGET /api/profiles/:npub/listsGET /api/profiles/:npub/lists/:dTag
/landing/boardsdirectory/b/[slug]board (New + Curated)/b/[slug]/submitsubmit listing/l/[eventId]listing detail/p/[npub]profile/lists/newcreate personal list
- Client builds event locally
- Uses NIP-07 if available (
window.nostr) - Falls back to JSON copy if NIP-07 is not available
- Publishes signed event directly to relays via
nostr-tools
- No file hosting, no peer stats, no IPFS fetching.
- Backend is read-only; all writes go to Nostr relays.