From 6853a2f7c9128fc9c111db7a80021b345c151104 Mon Sep 17 00:00:00 2001

From: DanConwayDev

Date: Mon, 22 Dec 2025 20:58:58 +0000

Subject: [PATCH] feat: add NIP-34 user grasp list rendering

because you wanted to know what it feels like:

nostr:nevent1qvzqqqqqqypzqla9dawkjc4trc7dgf88trpsq2uxvhmmpkxua607nc5g6a634sv5qyd8wumn8ghj7urewfsk66ty9enxjct5dfskvtnrdakj7qgmwaehxw309a6xsetxdaex2um59ehx7um5wgcjucm0d5hsqgxwfrfg9kvh99tj6adq5v2spwm9vhnp76zljuseqcpz4nd7w9d6pg000a03

---

src/components/nostr/kinds/GraspListDetailRenderer.tsx | 34 ++++++++++++++++++++++++++++++++++

src/components/nostr/kinds/GraspListRenderer.tsx | 39 +++++++++++++++++++++++++++++++++++++++

src/components/nostr/kinds/index.tsx | 4 ++++

src/constants/kinds.ts | 7 +++++++

src/data/nostr-kinds-schema.yaml | 11 +++++++++++

5 files changed, 95 insertions(+)

create mode 100644 src/components/nostr/kinds/GraspListDetailRenderer.tsx

create mode 100644 src/components/nostr/kinds/GraspListRenderer.tsx

diff --git a/src/components/nostr/kinds/GraspListDetailRenderer.tsx b/src/components/nostr/kinds/GraspListDetailRenderer.tsx

new file mode 100644

index 0000000..b3c9475

--- /dev/null

+++ b/src/components/nostr/kinds/GraspListDetailRenderer.tsx

@@ -0,0 +1,34 @@

+import { NostrEvent } from "@/types/nostr";

+import { RelayLink } from "../RelayLink";

+

+/**

+ * Kind 10317 Detail Renderer - User Grasp List (Detail View)

+ * Shows full list of grasp service relays

+ */

+export function Kind10317DetailRenderer({ event }: { event: NostrEvent }) {

+ // Extract grasp relay URLs from g tags

+ const graspRelays = event.tags

+ .filter((tag) => tag[0] === "g" && tag[1])

+ .map((tag) => tag[1]);

+

+ if (graspRelays.length === 0) {

+ return (

+

+ No grasp relays configured

+

+ );

+ }

+

+ return (

+

+ {graspRelays.map((url, index) => (

+

+ key={`${url}-${index}`}

+ url={url}

+ urlClassname="text-md underline decoration-dotted"

+ iconClassname="size-4"

+ />

+ ))}

+

+ );

+}

diff --git a/src/components/nostr/kinds/GraspListRenderer.tsx b/src/components/nostr/kinds/GraspListRenderer.tsx

new file mode 100644

index 0000000..ff1b2b8

--- /dev/null

+++ b/src/components/nostr/kinds/GraspListRenderer.tsx

@@ -0,0 +1,39 @@

+import { BaseEventProps, BaseEventContainer } from "./BaseEventRenderer";

+import { RelayLink } from "../RelayLink";

+

+/**

+ * Kind 10317 Renderer - User Grasp List (Feed View)

+ * Shows list of grasp service relays

+ */

+export function Kind10317Renderer({ event }: BaseEventProps) {

+ // Extract grasp relay URLs from g tags

+ const graspRelays = event.tags

+ .filter((tag) => tag[0] === "g" && tag[1])

+ .map((tag) => tag[1]);

+

+ if (graspRelays.length === 0) {

+ return (

+

+

+ No grasp relays configured

+

+

+ );

+ }

+

+ return (

+

+

+ {graspRelays.map((url, index) => (

+

+ key={`${url}-${index}`}

+ url={url}

+ className="py-0.5 hover:bg-none"

+ iconClassname="size-4"

+ urlClassname="underline decoration-dotted"

+ />

+ ))}

+

+

+ );

+}

diff --git a/src/components/nostr/kinds/index.tsx b/src/components/nostr/kinds/index.tsx

index b251e88..989d4de 100644

--- a/src/components/nostr/kinds/index.tsx

+++ b/src/components/nostr/kinds/index.tsx

@@ -25,6 +25,8 @@ import { Kind9802Renderer } from "./HighlightRenderer";

import { Kind9802DetailRenderer } from "./HighlightDetailRenderer";

import { Kind10002Renderer } from "./RelayListRenderer";

import { Kind10002DetailRenderer } from "./RelayListDetailRenderer";

+import { Kind10317Renderer } from "./GraspListRenderer";

+import { Kind10317DetailRenderer } from "./GraspListDetailRenderer";

import { Kind30023Renderer } from "./ArticleRenderer";

import { Kind30023DetailRenderer } from "./ArticleDetailRenderer";

import { CommunityNIPRenderer } from "./CommunityNIPRenderer";

@@ -74,6 +76,7 @@ const kindRenderers: Record> = {

9802: Kind9802Renderer, // Highlight

777: SpellRenderer, // Spell (Grimoire)

10002: Kind10002Renderer, // Relay List Metadata (NIP-65)

+ 10317: Kind10317Renderer, // User Grasp List (NIP-34)

10006: GenericRelayListRenderer, // Blocked Relays (NIP-51)

10007: GenericRelayListRenderer, // Search Relays (NIP-51)

10012: GenericRelayListRenderer, // Favorite Relays (NIP-51)

@@ -137,6 +140,7 @@ const detailRenderers: Record<

1621: IssueDetailRenderer, // Issue Detail (NIP-34)

9802: Kind9802DetailRenderer, // Highlight Detail

10002: Kind10002DetailRenderer, // Relay List Detail (NIP-65)

+ 10317: Kind10317DetailRenderer, // User Grasp List Detail (NIP-34)

777: SpellDetailRenderer, // Spell Detail

30023: Kind30023DetailRenderer, // Long-form Article Detail

30311: LiveActivityDetailRenderer, // Live Streaming Event Detail (NIP-53)

diff --git a/src/constants/kinds.ts b/src/constants/kinds.ts

index 6d51b1f..284595a 100644

--- a/src/constants/kinds.ts

+++ b/src/constants/kinds.ts

@@ -847,6 +847,13 @@ export const EVENT_KINDS: Record = {

nip: "66",

icon: Activity,

},

+ 10317: {

+ kind: 10317,

+ name: "Grasp List",

+ description: "User grasp list",

+ nip: "34",

+ icon: FolderGit2,

+ },

// 10312: {

// kind: 10312,

// name: "Room Presence",

diff --git a/src/data/nostr-kinds-schema.yaml b/src/data/nostr-kinds-schema.yaml

index 7f172c2..fb10587 100644

--- a/src/data/nostr-kinds-schema.yaml

+++ b/src/data/nostr-kinds-schema.yaml

@@ -1318,6 +1318,17 @@ kinds:

type: empty

tags: []

+ 10317:

+ description: User grasp list

+ content:

+ type: empty

+ tags:

+ -

+ name: g

+ next:

+ type: relay

+ required: true

+

10377:

description: Proxy Announcement

content:

--

libgit2 1.9.1

Reply to this note

Please Login to reply.

Discussion

No replies yet.