{"id":"81ab3731f491f948d7986889ca8bfe52d83b53481f711e4add8aee4696ef57a5","pubkey":"0f563fe2cfdf180cb104586b95873379a0c1fdcfbc301a80c8255f33d15f039d","created_at":1784041516,"kind":30817,"tags":[["d","pinboards"],["title","Pinboards"],["alt","Nostr Implementation Possibility: Pinboards"],["k","30067","Pinboard"],["k","39067","Pin"],["client","NostrHub"]],"content":"Pinboards\n---------\n\n`draft` `optional`\n\nThis NIP defines a pinboard system for Nostr, enabling users to create visual collections of curated content. Pinboards use a two-event architecture that separates board metadata from individual pins, allowing for mixed-content curation, collaborative boards, cross-board pinning, and profile-level pins.\n\n## Motivation\n\nNIP-51 defines list kinds for content curation, but these have structural limitations that Pinboards attempt to address.\n\n### Content-Type Segregation\n\nNIP-51 defines separate curation set kinds for specific content types:\n\n| Kind | Content Type | Expected Tags |\n|------|--------------|---------------|\n| 30004 | Articles/notes | `a` (kind:30023), `e` (kind:1) |\n| 30005 | Videos | `e` (kind:21) |\n| 30006 | Pictures | `e` (kind:20) |\n\nThis forces users to maintain separate lists for different media. A \"Japan Trip 2024\" collection requires:\n - A kind 30006 set for photos\n - A kind 30005 set for videos\n - A kind 30004 set for blog articles\n - A kind 30003 set for external links\n\n**Pinboards allow heterogeneous content in a single collection.** One \"Japan Trip 2024\" pinboard can contain photos, videos, articles, notes, external links, books, podcasts—organized together thematically.\n\n### Additional NIP-51 Limitations\n\n| Limitation | NIP-51 Lists | Pinboards |\n|------------|--------------|-----------|\n| Content types | Segregated by kind | Mixed in one board |\n| Item storage | All embedded in one event | Separate events per pin |\n| Collaboration | Single author only | Optional multi-author |\n| Cross-posting | Items belong to one list | Pins reference multiple boards |\n| Attribution | List owner only | Per-pin author tracking |\n| Scalability | Limited by event size | Unlimited pins |\n\n## Event Kinds\n\n### Kind 30067: Pinboard\n\nA parameterized replaceable event containing board metadata. Pins are stored separately.\n\n**Required Tags:**\n\n| Tag | Description |\n|-----|-------------|\n| `d` | Unique identifier (used to generate `naddr`) |\n| `title` | Human-readable board title |\n\n**Optional Tags:**\n\n| Tag | Description |\n|-----|-------------|\n| `description` | Extended description of the board |\n| `image` | Cover image URL |\n| `t` | Hashtag for categorization (repeatable) |\n| `collaborative` | Presence-only flag; when present, anyone can pin to this board |\n\n**Content:** Empty string or optional description text.\n\n**Example:**\n```json\n{\n  \"kind\": 30067,\n  \"pubkey\": \"<board-creator-pubkey>\",\n  \"created_at\": 1704067200,\n  \"content\": \"\",\n  \"tags\": [\n    [\"d\", \"japan-trip-2024\"],\n    [\"title\", \"Japan Trip 2024\"],\n    [\"description\", \"Photos, videos, and memories from my trip to Japan\"],\n    [\"image\", \"https://example.com/mt-fuji.jpg\"],\n    [\"t\", \"japan\"],\n    [\"t\", \"travel\"],\n    [\"collaborative\"]\n  ]\n}\n```\n\n**Board Address Format:** `30067:<pubkey>:<d-tag>`\n\n### Kind 39067: Pin\n\nA regular event representing a single pinned item. Unlike NIP-51 lists where items are embedded as tags, each pin is its own event—enabling per-item authorship, comments, and flexible board membership.\n\n**Required Tags:**\n\n| Tag | Description |\n|-----|-------------|\n| `d` | Unique identifier (used to generate `naddr`) |\n\n#### Board Reference Tags (Optional)\n\n| Tag | Description |\n|-----|-------------|\n| `A` | Board coordinate: `30067:<pubkey>:<d-tag>` (repeatable for multi-board pinning) |\n\nA pin with no board `A` tags is a \"profile pin\" displayed on the author's profile.\n\n#### Content Reference Tags (Exactly One Required)\n\nPins reference content using two methods:\n\n**For Nostr events** — use `e` or `a` tags:\n\n| Tag | Description |\n|-----|-------------|\n| `e` | Event reference for notes (kind:1), pictures (kind:20), videos (kind:21/22), etc. |\n| `a` | Coordinate reference for articles (kind:30023), bookmarks (kind:39701), recipes, etc. |\n\n**For external content** — use NIP-73 `i` tags:\n\n| Tag | Description |\n|-----|-------------|\n| `i` | External content ID per [NIP-73](73.md) |\n| `k` | External content kind per [NIP-73](73.md) |\n\nSupported external content types include:\n\n| Type | `i` tag format | `k` tag |\n|------|----------------|---------|\n| Web URLs | `https://example.com/page` | `web` |\n| Books | `isbn:9780765382030` | `isbn` |\n| Podcasts | `podcast:guid:<guid>` | `podcast:guid` |\n| Podcast Episodes | `podcast:item:guid:<guid>` | `podcast:item:guid` |\n| Movies | `isan:0000-0000-401A-0000-7` | `isan` |\n| Academic Papers | `doi:10.1000/xyz123` | `doi` |\n| Locations | `geo:<geohash>` | `geo` |\n\n#### Metadata Tags (Optional)\n\n| Tag | Description |\n|-----|-------------|\n| `title` | Custom title for this pin |\n| `t` | Hashtag (repeatable) |\n\n**Content:** Optional comment about the pinned item.\n\n## Examples\n\n### Mixed-content board\n\nA single \"Japan Trip 2024\" pinboard containing photos, videos, articles, notes, and external links:\n\n```json\n// Photo (references kind:20 picture event)\n{\n  \"kind\": 39067,\n  \"content\": \"Sunrise at Mt. Fuji\",\n  \"tags\": [\n    [\"d\", \"<picture-event-id>\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"e\", \"<picture-event-id>\", \"wss://relay.example.com\"]\n  ]\n}\n\n// Video (references kind:21 video event)\n{\n  \"kind\": 39067,\n  \"content\": \"The bullet train experience\",\n  \"tags\": [\n    [\"d\", \"<video-event-id>\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"e\", \"<video-event-id>\", \"wss://relay.example.com\"]\n  ]\n}\n\n// Article (references kind:30023 long-form content)\n{\n  \"kind\": 39067,\n  \"content\": \"Great tips for first-time visitors\",\n  \"tags\": [\n    [\"d\", \"30023:<author>:tokyo-guide\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"a\", \"30023:<author>:tokyo-guide\", \"wss://relay.example.com\"]\n  ]\n}\n\n// Note (references kind:1 note)\n{\n  \"kind\": 39067,\n  \"content\": \"Best ramen I've ever had\",\n  \"tags\": [\n    [\"d\", \"<note-event-id>\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"e\", \"<note-event-id>\", \"wss://relay.example.com\"]\n  ]\n}\n\n// External URL (NIP-73)\n{\n  \"kind\": 39067,\n  \"content\": \"Where I stayed in Tokyo\",\n   \"tags\": [\n    [\"d\", \"https://booking.example.com/tokyo-hotel\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"i\", \"https://booking.example.com/tokyo-hotel\"],\n    [\"k\", \"web\"],\n    [\"title\", \"Tokyo Hotel Recommendation\"]\n  ]\n}\n\n// Book recommendation (NIP-73)\n{\n  \"kind\": 39067,\n  \"content\": \"Read this before visiting\",\n  \"tags\": [\n    [\"d\", \"isbn:9784805311981\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"i\", \"isbn:9784805311981\"],\n    [\"k\", \"isbn\"],\n    [\"title\", \"Japan Travel Guide\"]\n  ]\n}\n```\n\n### Pin to multiple boards\n\n```json\n{\n  \"kind\": 39067,\n  \"content\": \"\",\n  \"tags\": [\n    [\"d\", \"<picture-event-id>\"]\n    [\"A\", \"30067:<pubkey>:japan-trip-2024\"],\n    [\"A\", \"30067:<pubkey>:best-photos-2024\"],\n    [\"A\", \"30067:<pubkey>:travel-memories\"],\n    [\"e\", \"<picture-event-id>\"]\n  ]\n}\n```\n\n### Profile pin (no board)\n\n```json\n{\n  \"kind\": 39067,\n  \"content\": \"My favorite photo ever\",\n  \"tags\": [\n    [\"d\", \"<picture-event-id>\"]\n    [\"e\", \"<picture-event-id>\"],\n    [\"t\", \"photography\"]\n  ]\n}\n```\n\n### Pin a pinboard to another pinboard (meta-curation):\n\n```json\n{\n   \"kind\": 39067,\n   \"content\": \"Amazing travel photography collection\",\n   \"tags\": [\n     [\"d\", \"30067:<curator>:japan-trip-2024\"]\n     [\"A\", \"30067:<owner>:best-of-2024\"],\n     [\"a\", \"30067:<curator>:japan-trip-2024\"]\n   ]\n}\n```\n\n### Using NIP-B0 bookmark (optional)\n\nUsers who prefer to manage their web bookmarks as events can create a NIP-B0 bookmark first, then pin it:\n\n```json\n{\n  \"kind\": 39067,\n  \"content\": \"Great resource\",\n  \"tags\": [\n    [\"d\", \"39701:<pubkey>:github.com/nostr-protocol/nips\"]\n    [\"A\", \"30067:<pubkey>:dev-resources\"],\n    [\"a\", \"39701:<pubkey>:github.com/nostr-protocol/nips\"]\n  ]\n}\n```\n\nThis is optional—users can also pin URLs directly using NIP-73 `i` tags.\n\n## Collaboration Model\n\n### Private Boards (Default)\n\nWithout the `collaborative` tag, only the board owner's pins are displayed.\n\n**Filter for private board pins:**\n```json\n{\n  \"kinds\": [39067],\n  \"authors\": [\"<board-owner-pubkey>\"],\n  \"#A\": [\"30067:<board-owner-pubkey>:<d-tag>\"]\n}\n```\n\n### Collaborative Boards\n\nWith the `collaborative` tag present, all pins referencing the board are displayed regardless of author.\n\n**Filter for collaborative board pins:**\n```json\n{\n  \"kinds\": [39067],\n  \"#A\": [\"30067:<board-owner-pubkey>:<d-tag>\"]\n}\n```\n\n## Content Type Inference\n\nClients infer content type from the reference to provide appropriate rendering:\n\n**For `e` tag references:** Fetch the event and use its `kind`:\n\n| Kind | Content Type |\n|------|--------------|\n| 1 | Note |\n| 20 | Picture |\n| 21, 22 | Video |\n\n**For `a` tag references:** Parse kind from coordinate (`kind:pubkey:d-tag`):\n\n| Kind | Content Type |\n|------|--------------|\n| 30023 | Long-form article |\n| 30078 | Application data (recipes, etc.) |\n| 30311 | Live event |\n| 31922, 31923 | Calendar event |\n| 34550 | Community |\n| 30067 | Nested pinboard |\n| 39701 | Web bookmark (NIP-B0) |\n\n**For `i` tag references:** Use the `k` tag value:\n\n| `k` value | Content Type |\n|-----------|--------------|\n| `web` | Web link |\n| `isbn` | Book |\n| `podcast:guid` | Podcast |\n| `podcast:item:guid` | Podcast episode |\n| `isan` | Movie |\n| `doi` | Academic paper |\n| `geo` | Location |\n\n## Client Behavior\n\n### Displaying Boards\n\n1. Fetch board event (kind 30067) by coordinate\n2. Fetch pins using appropriate filter based on `collaborative` flag\n3. For each pin:\n   - If `e` or `a` tag: fetch referenced Nostr event\n   - If `i` tag: render based on content type, optionally fetch metadata\n4. Display in masonry/grid layout with content-type-aware rendering\n\n### Creating Pins\n\n1. Allow selection of target board(s) or \"profile pin\"\n2. For Nostr content: use `e` or `a` tags\n3. For external content: use NIP-73 `i`/`k` tags\n4. Accept optional title, comment, and hashtags\n5. Publish kind 39067 with appropriate tags\n\n### Profile Pins\n\nDisplay pins by user that have no board `A` tag:\n```json\n{\"kinds\": [39067], \"authors\": [\"<pubkey>\"]}\n```\nFilter client-side for pins without `30067:` coordinate references.\n\n## Engagement\n\nBoards support NIP-25 reactions and NIP-57 zaps:\n\n```json\n{\n  \"kind\": 7,\n  \"content\": \"+\",\n  \"tags\": [\n    [\"d\", \"<note-event-id>\"]\n    [\"a\", \"30067:<pubkey>:<d-tag>\"],\n    [\"p\", \"<board-author-pubkey>\"]\n  ]\n}\n```\n\n## Comparison with NIP-51\n\n| Feature | NIP-51 Curation Sets | Pinboards |\n|---------|---------------------|-----------|\n| Content types per list | Single (30004=articles, 30005=videos, 30006=pictures) | **Any type in one board** |\n| External content | Limited | **Full NIP-73 support** (URLs, books, podcasts, movies, papers) |\n| Item storage | Embedded in list event | Separate pin events |\n| Collaboration | No | Yes (`collaborative` flag) |\n| Multi-list membership | No | Yes (multiple `A` tags) |\n| Profile-level items | No | Yes (pins without board) |\n| Per-item attribution | No (list owner only) | Yes (pin author tracked) |\n| Per-item comments | No | Yes (pin content field) |\n| Scalability | Event size limited | Unlimited |\n\n## Security Considerations\n\n- Validate URLs in `i` tags to prevent `javascript:` or `data:` scheme attacks\n- Sanitize user content before rendering\n- Collaborative boards may receive spam; consider reputation-based filtering\n\n## References\n\n- [NIP-51: Lists](51.md)\n- [NIP-73: External Content IDs](73.md)\n- [NIP-B0: Web Bookmarks](B0.md)\n- [NIP-25: Reactions](25.md)\n- [NIP-22: Comment](22.md)\n- [NIP-57: Lightning Zaps](57.md)","sig":"8dbc4443e9f452d9bdce31e4e126794789cdfb9fa8d2d49eed889acc0dd1d09f374963c29605ccc47c58f0d7e10c84022984b4abadaee1594a221ee67149548d"}