diff --git a/src/components/EventDetailViewer.tsx b/src/components/EventDetailViewer.tsx
index fa254d5..43c3a70 100644
--- a/src/components/EventDetailViewer.tsx
+++ b/src/components/EventDetailViewer.tsx
@@ -28,6 +28,7 @@ import { useReqTimelineEnhanced } from "@/hooks/useReqTimelineEnhanced";
import { applySpellParameters, decodeSpell } from "@/lib/spell-conversion";
import { parseReqCommand } from "@/lib/req-parser";
import { AGGREGATOR_RELAYS } from "@/services/loaders";
+import { KindBadge } from "./KindBadge";
export interface EventDetailViewerProps {
pointer: EventPointer | AddressPointer;
@@ -372,7 +373,7 @@ export function EventDetailViewer({ pointer }: EventDetailViewerProps) {
{/* Rendered Content */}
-
+
@@ -385,16 +386,44 @@ export function EventDetailViewer({ pointer }: EventDetailViewerProps) {
defaultValue={eventSpells[0]?.id}
className="flex flex-col h-full"
>
-
- {eventSpells.map((spell) => (
-
- {spell.name || spell.alias || "Untitled Spell"}
-
- ))}
+
+ {eventSpells.map((spell) => {
+ // Extract kinds from spell for display
+ const spellKinds = (() => {
+ try {
+ if (spell.event) {
+ const decoded = decodeSpell(spell.event);
+ return decoded.filter.kinds?.slice(0, 3) || [];
+ }
+ // For local spells, parse command
+ const commandWithoutPrefix = spell.command
+ .replace(/^\s*(req|count)\s+/i, "")
+ .trim();
+ const tokens = commandWithoutPrefix.split(/\s+/);
+ const parsed = parseReqCommand(tokens);
+ return parsed.filter.kinds?.slice(0, 3) || [];
+ } catch {
+ return [];
+ }
+ })();
+
+ return (
+
+ {spellKinds.length > 0 && (
+
+ {spellKinds.map((kind) => (
+
+ ))}
+
+ )}
+ {spell.name || spell.alias || "Untitled Spell"}
+
+ );
+ })}
{/* Spell Tab Contents */}
diff --git a/src/components/ProfileViewer.tsx b/src/components/ProfileViewer.tsx
index d218a8f..e8f4707 100644
--- a/src/components/ProfileViewer.tsx
+++ b/src/components/ProfileViewer.tsx
@@ -42,6 +42,7 @@ import { applySpellParameters, decodeSpell } from "@/lib/spell-conversion";
import { parseReqCommand } from "@/lib/req-parser";
import { useOutboxRelays } from "@/hooks/useOutboxRelays";
import { AGGREGATOR_RELAYS } from "@/services/loaders";
+import { KindBadge } from "./KindBadge";
export interface ProfileViewerProps {
pubkey: string;
@@ -615,7 +616,7 @@ export function ProfileViewer({ pubkey }: ProfileViewerProps) {
{/* Profile Content */}
-
+
{!profile && !profileEvent &&
}
{!profile && profileEvent && (
@@ -713,16 +714,44 @@ export function ProfileViewer({ pubkey }: ProfileViewerProps) {
defaultValue={pubkeySpells[0]?.id}
className="flex flex-col h-full"
>
-
- {pubkeySpells.map((spell) => (
-
- {spell.name || spell.alias || "Untitled Spell"}
-
- ))}
+
+ {pubkeySpells.map((spell) => {
+ // Extract kinds from spell for display
+ const spellKinds = (() => {
+ try {
+ if (spell.event) {
+ const decoded = decodeSpell(spell.event);
+ return decoded.filter.kinds?.slice(0, 3) || [];
+ }
+ // For local spells, parse command
+ const commandWithoutPrefix = spell.command
+ .replace(/^\s*(req|count)\s+/i, "")
+ .trim();
+ const tokens = commandWithoutPrefix.split(/\s+/);
+ const parsed = parseReqCommand(tokens);
+ return parsed.filter.kinds?.slice(0, 3) || [];
+ } catch {
+ return [];
+ }
+ })();
+
+ return (
+
+ {spellKinds.length > 0 && (
+
+ {spellKinds.map((kind) => (
+
+ ))}
+
+ )}
+ {spell.name || spell.alias || "Untitled Spell"}
+
+ );
+ })}
{/* Spell Tab Contents */}
diff --git a/src/components/RelayViewer.tsx b/src/components/RelayViewer.tsx
index 20a6f31..6b2b5e1 100644
--- a/src/components/RelayViewer.tsx
+++ b/src/components/RelayViewer.tsx
@@ -12,6 +12,7 @@ import { applySpellParameters, decodeSpell } from "@/lib/spell-conversion";
import { parseReqCommand } from "@/lib/req-parser";
import { useMemo } from "react";
import { NIPBadge } from "./NIPBadge";
+import { KindBadge } from "./KindBadge";
import { SpellHeader } from "./timeline/SpellHeader";
export interface RelayViewerProps {
@@ -237,7 +238,7 @@ export function RelayViewer({ url }: RelayViewerProps) {
return (
{/* Relay Info Content */}
-
+
{/* Header */}
@@ -314,16 +315,44 @@ export function RelayViewer({ url }: RelayViewerProps) {
defaultValue={relaySpells[0]?.id}
className="flex flex-col h-full"
>
-
- {relaySpells.map((spell) => (
-
- {spell.name || spell.alias || "Untitled Spell"}
-
- ))}
+
+ {relaySpells.map((spell) => {
+ // Extract kinds from spell for display
+ const spellKinds = (() => {
+ try {
+ if (spell.event) {
+ const decoded = decodeSpell(spell.event);
+ return decoded.filter.kinds?.slice(0, 3) || [];
+ }
+ // For local spells, parse command
+ const commandWithoutPrefix = spell.command
+ .replace(/^\s*(req|count)\s+/i, "")
+ .trim();
+ const tokens = commandWithoutPrefix.split(/\s+/);
+ const parsed = parseReqCommand(tokens);
+ return parsed.filter.kinds?.slice(0, 3) || [];
+ } catch {
+ return [];
+ }
+ })();
+
+ return (
+
+ {spellKinds.length > 0 && (
+
+ {spellKinds.map((kind) => (
+
+ ))}
+
+ )}
+ {spell.name || spell.alias || "Untitled Spell"}
+
+ );
+ })}
{/* Spell Tab Contents */}