diff --git a/TODO.md b/TODO.md
index cb2744f..080c1d9 100644
--- a/TODO.md
+++ b/TODO.md
@@ -34,3 +34,6 @@ avoid inserting `br`, look into noStrudel's eol metadata
## TODO: window crashes on unsupported kind event
## TODO: app-wide error boundary. splash crash screen.
+## TODO: collapsible relay list -> user relaylink without inbox/outbox icon
+
+## TODO: use NIP badges everywhere for linking NIPs
diff --git a/src/components/KindsViewer.tsx b/src/components/KindsViewer.tsx
new file mode 100644
index 0000000..4d24dc6
--- /dev/null
+++ b/src/components/KindsViewer.tsx
@@ -0,0 +1,97 @@
+import { getKindInfo } from "@/constants/kinds";
+import Command from "./Command";
+
+// Supported kinds with rich renderers
+const SUPPORTED_KINDS = [
+ 0, // Profile Metadata
+ 1, // Short Text Note
+ 3, // Contact List
+ 6, // Repost
+ 7, // Reaction
+ 20, // Picture (NIP-68)
+ 21, // Video Event (NIP-71)
+ 22, // Short Video (NIP-71)
+ 1063, // File Metadata (NIP-94)
+ 1111, // Post
+ 9735, // Zap Receipt
+ 9802, // Highlight
+ 10002, // Relay List Metadata (NIP-65)
+ 30023, // Long-form Article
+];
+
+/**
+ * KindsViewer - System introspection command
+ * Shows all event kinds with rich rendering support
+ */
+export default function KindsViewer() {
+ // Sort kinds in ascending order
+ const sortedKinds = [...SUPPORTED_KINDS].sort((a, b) => a - b);
+
+ return (
+
+
+ {/* Header */}
+
+
+ Supported Event Kinds ({sortedKinds.length})
+
+
+ Event kinds with rich rendering support in Grimoire. Default kinds
+ display raw content only.
+
+
+
+ {/* Kind List */}
+
+ {sortedKinds.map((kind) => {
+ const kindInfo = getKindInfo(kind);
+ const Icon = kindInfo?.icon;
+
+ return (
+
+
+ {/* Icon */}
+
+ {Icon ? (
+
+ ) : (
+
+ {kind}
+
+ )}
+
+
+ {/* Content */}
+
+
+
+ {kind}
+
+
+ {kindInfo?.name || `Kind ${kind}`}
+
+
+
+ {kindInfo?.description || "No description available"}
+
+ {kindInfo?.nip && (
+
+ )}
+
+
+
+ );
+ })}
+
+
+
+ );
+}
diff --git a/src/components/WindowRenderer.tsx b/src/components/WindowRenderer.tsx
index d1494c4..28ccccb 100644
--- a/src/components/WindowRenderer.tsx
+++ b/src/components/WindowRenderer.tsx
@@ -11,6 +11,7 @@ import EncodeViewer from "./EncodeViewer";
import DecodeViewer from "./DecodeViewer";
import { RelayViewer } from "./RelayViewer";
import KindRenderer from "./KindRenderer";
+import KindsViewer from "./KindsViewer";
import Feed from "./nostr/Feed";
import { WinViewer } from "./WinViewer";
import { DebugViewer } from "./DebugViewer";
@@ -101,6 +102,9 @@ export function WindowRenderer({ window, onClose }: WindowRendererProps) {
case "kind":
content = ;
break;
+ case "kinds":
+ content = ;
+ break;
case "man":
content = ;
break;
diff --git a/src/types/app.ts b/src/types/app.ts
index 69ad082..f19e803 100644
--- a/src/types/app.ts
+++ b/src/types/app.ts
@@ -3,6 +3,7 @@ import { MosaicNode } from "react-mosaic-component";
export type AppId =
| "nip"
| "kind"
+ | "kinds"
| "man"
| "feed"
| "win"
diff --git a/src/types/man.ts b/src/types/man.ts
index eae477f..904c92a 100644
--- a/src/types/man.ts
+++ b/src/types/man.ts
@@ -87,6 +87,18 @@ export const manPages: Record = {
category: "System",
defaultProps: { cmd: "help" },
},
+ kinds: {
+ name: "kinds",
+ section: "1",
+ synopsis: "kinds",
+ description:
+ "Display all Nostr event kinds with rich rendering support in Grimoire. Shows kind numbers, names, descriptions, and links to their defining NIPs.",
+ examples: ["kinds View all supported event kinds"],
+ seeAlso: ["kind", "nip", "man"],
+ appId: "kinds",
+ category: "System",
+ defaultProps: {},
+ },
// debug: {
// name: "debug",
// section: "1",