--- name: nostr-comments description: Implement Nostr comment systems, add discussion features to posts/articles, build community interaction features, or attach comments to any external content identifier including URLs, hashtags, and NIP-73 identifiers (ISBN, podcast GUIDs, geohashes, movie ISANs, blockchain transactions, and more). --- # Adding Nostr Comments Sections This skill provides a complete commenting system using NIP-22 (kind 1111) comments that can be added to any Nostr event, URL, hashtag, or NIP-73 external content identifier. The `CommentsSection` component renders a lightweight, inline commenting interface with threaded replies, user authentication, and a per-comment actions menu (Open in Ditto, Delete own comment). **The comment system is not included in the project by default.** When the user wants comment functionality, follow the setup instructions below to install the files. ## Files Provided by This Skill All files live under `.agents/skills/nostr-comments/files/` and must be copied into `src/` preserving the directory structure: | Skill file | Copy to | |---|---| | `files/hooks/useComments.ts` | `src/hooks/useComments.ts` | | `files/hooks/usePostComment.ts` | `src/hooks/usePostComment.ts` | | `files/components/comments/Comment.tsx` | `src/components/comments/Comment.tsx` | | `files/components/comments/CommentForm.tsx` | `src/components/comments/CommentForm.tsx` | | `files/components/comments/CommentsSection.tsx` | `src/components/comments/CommentsSection.tsx` | ## Setup Instructions ### 1. Dependencies No extra npm packages are required — the skill uses only packages already present in the template (`@nostrify/nostrify`, `@nostrify/react`, `@tanstack/react-query`, `nostr-tools`, `date-fns`, `lucide-react`, `react-router-dom`, and shadcn/ui components). ### 2. Copy the Skill Files Into `src/` Copy every file listed in the table above from `.agents/skills/nostr-comments/files/` into its corresponding location under `src/`. Preserve the exact paths — the files use `@/hooks/...` and `@/components/...` imports that depend on these locations. ### 3. Required Project Components The comment components depend on pieces that already ship with the template: - `@/components/NoteContent` — renders comment text (used by `Comment.tsx`) - `@/components/auth/LoginArea` — shown to logged-out users (used by `CommentForm.tsx`) - `@/components/ui/alert-dialog` — confirms deletion (used by `Comment.tsx`) - `@/hooks/useAuthor` — fetches comment author profile (used by `Comment.tsx`) - `@/hooks/useCurrentUser` — determines whether to show the composer and the Delete action (used by `CommentForm.tsx`, `Comment.tsx`) - `@/hooks/useNostrPublish` — publishes kind 1111 comments and kind 5 deletion requests (used by `usePostComment.ts`, `Comment.tsx`) - `@/hooks/useToast` — user feedback on delete success/failure (used by `Comment.tsx`) All of these are standard in the template; no extra work is needed beyond copying the skill files. ## Basic Usage `CommentsSection` renders without an outer card, title, or header — it's just the composer followed by the threaded comment list. Wrap it in whatever page layout you want: ```tsx import { CommentsSection } from "@/components/comments/CommentsSection"; function ArticlePage({ article }: { article: NostrEvent }) { return (
{/* Your article content */}
{/* article content */}
{/* Comments section — add your own heading if needed */}

Comments

); } ``` ## Per-Comment Actions Menu Each comment has a 3-dots menu with: - **Open in Ditto** — opens the comment at `https://ditto.pub/` in a new tab so users can view replies, react, or zap via Ditto. - **Delete** — only shown when the logged-in user is the comment's author. Publishes a NIP-09 (kind 5) deletion request tagging the comment's `id` and `kind`, then optimistically removes the comment from the cached query result via `queryClient.setQueriesData`. Deletion is not guaranteed across the network — the `AlertDialog` confirmation makes this clear to the user. ## Props and Customization The `CommentsSection` component accepts the following props: - **`root`** (required): The root to comment on. Accepts three types: - `NostrEvent` — comment on a Nostr event (kind 1 note, long-form article, etc.) - `URL` — comment on an external identifier: web URLs (`new URL("https://...")`) or any NIP-73 identifier except hashtags (e.g. `new URL("isbn:9780765382030")`, `new URL("iso3166:US")`) - `#${string}` — NIP-73 hashtag only (e.g. `"#bitcoin"`); this template string type is exclusively for hashtags and must not be used for other NIP-73 identifiers - **`emptyStateMessage`**: Message shown when no comments exist (default: "No comments yet") - **`emptyStateSubtitle`**: Subtitle for empty state (default: "Be the first to share your thoughts!") - **`className`**: Additional CSS classes applied to the outer `
` (it's a plain `space-y-6` container, no card/border) - **`limit`**: Maximum number of comments to load (default: 500) ```tsx ``` ## Commenting on URLs The comments system supports commenting on external URLs, making it useful for web pages, articles, or any online content: ```tsx ``` ## Commenting on Hashtags Pass a hashtag string (`#${string}` format) to attach comments to a topic. The hashtag must be lowercase: ```tsx // Comments for the #bitcoin hashtag // Comments for a community-specific tag ``` ## Commenting on NIP-73 External Content Identifiers NIP-73 defines a standard set of external content IDs. All NIP-73 identifiers (except hashtags) are passed as `URL` objects — the identifier string is used directly as the URL: ### Books (ISBN) ```tsx // ISBN must be without hyphens ``` ### Podcasts ```tsx // Podcast feed // Podcast episode ``` ### Movies (ISAN) ```tsx // ISAN without version part ``` ### Geohashes ```tsx // Geohash must be lowercase ``` ### Countries (ISO 3166) ```tsx // ISO 3166 codes must be uppercase // Subdivision (state/province) ``` ### Academic Papers (DOI) ```tsx // DOI must be lowercase ``` ### Blockchain Transactions and Addresses ```tsx // Bitcoin transaction // Ethereum address ```