mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-10 07:27:23 +02:00
* feat: implement NIP-89 app definitions and recommendations with rich rendering
Add comprehensive support for NIP-89 Application Handlers (kind 31990) and
Handler Recommendations (kind 31989) with rich, interactive visualizations.
Core Implementation:
- nip89-helpers.ts: Utility functions for extracting NIP-89 event metadata
- App name, description, image from kind 31990 content JSON
- Supported kinds from k tags
- Platform URLs (web, ios, android) from platform tags
- Handler references from kind 31989 a tags
- URL template substitution for <bech32> placeholders
Feed Renderers:
- ApplicationHandlerRenderer (31990): Shows app name, supported kinds as
clickable KindBadges (max 8 in feed), and platform badges
- HandlerRecommendationRenderer (31989): Shows recommended kind and handler
list (max 3 in feed) with platform indicators
Detail Renderers:
- ApplicationHandlerDetailRenderer (31990): Comprehensive view with app info,
all supported kinds in grid layout (clickable), platform URLs with copy
buttons, and metadata JSON viewer
- HandlerRecommendationDetailRenderer (31989): Full view with platform
filtering tabs, expanded handler cards showing app details, and raw
reference data
Features:
- Clickable KindBadges throughout for quick navigation
- Platform-aware filtering and display
- Fetches referenced kind 31990 events reactively
- Copy buttons for URL templates
- Platform icons (web, ios, android)
- Follows existing Grimoire patterns (SpellRenderer for kinds display,
CodeSnippetDetailRenderer for metadata sections)
Testing:
- Comprehensive test suite for nip89-helpers (50+ test cases)
- Tests cover all helper functions with edge cases
- Follows existing test patterns from codebase
Registry:
- Added both kinds (31989, 31990) to kindRenderers and detailRenderers
- Automatically expands supported kinds count in KindsViewer
* fix: remove unused imports and parameters in NIP-89 renderers
* fix: correct AddressPointer import and apply prettier formatting
- Change AddressPointer import from applesauce-core/helpers to nostr-tools/nip19
to match codebase conventions
- Auto-fix prettier formatting for nip89 files
* fix: add defensive type checks to prevent React error 31
- Add type guards in nip89-helpers to ensure string types
- Check metadata object structure before accessing properties
- Add fallbacks for undefined address.identifier values
- Prevents accidentally rendering objects as React children
* fix: stringify contentJson for CopyableJsonViewer and support 'about' field
- Fix React error 31: CopyableJsonViewer expects string, not object
- Add JSON.stringify() with pretty printing for metadata display
- Support both 'description' and 'about' fields in content JSON (common in kind 0)
- Add tests for 'about' field handling
* refactor: simplify NIP-89 detail renderers
Remove unnecessary metadata displays:
- Remove app image from ApplicationHandlerDetailRenderer
- Remove Event ID and Created timestamp from both detail renderers
- Remove Raw Metadata section from ApplicationHandlerDetailRenderer
- Remove Raw References section from HandlerRecommendationDetailRenderer
- Clean up unused imports (getAppImage, CopyableJsonViewer, useMemo, formatAddressPointer)
Keeps the UI focused on the essential information: app name, description,
supported kinds, and platform URLs.
* feat: add website display and filter non-platform tags
NIP-89 renderer improvements:
- Add getAppWebsite() helper to extract website from content JSON
- Display website URL in both feed and detail renderers with external link
- Filter out non-platform tags (r, t, client, alt, e, p, a) to prevent garbage display
- Remove relay hint display from HandlerRecommendationDetailRenderer
- Clean up unused relayHint parameter
Fixes the 'r r' tag appearing as a platform by properly excluding
common non-platform tags when detecting platform URLs.
* refactor: create reusable ExternalLink component for consistent styling
Create ExternalLink component following patterns from HighlightRenderer and
BookmarkRenderer with:
- Two variants: 'muted' (default, text-muted-foreground with underline)
and 'default' (text-primary with hover:underline)
- Three sizes: xs, sm, base
- Configurable icon display
- Consistent truncate behavior for long URLs
- Stop propagation on click
Apply to NIP-89 renderers:
- ApplicationHandlerRenderer: uses muted variant (feed view)
- ApplicationHandlerDetailRenderer: uses default variant (detail view)
This ensures consistent link styling across the entire application
and makes it easy to maintain a unified design language.
* refactor: consolidate JSON parsing into cached getAppMetadata helper
Performance optimization:
- Create getAppMetadata() helper that parses content JSON once and caches
the result using Symbol.for('nip89-metadata') as cache key
- All metadata helpers (getAppName, getAppDescription, getAppWebsite) now
use the cached metadata instead of parsing JSON multiple times
- Prevents redundant JSON.parse() calls when multiple helpers are used
Code cleanup - removed unused functions:
- getAppImage() - no longer used after removing image display
- getHandlersByPlatform() - filtering done in component state
- substituteTemplate() - not needed in current implementation
- hasPlaceholder() - utility never used
- formatAddressPointer() - not needed anymore
Updated tests:
- Replace getAppImage tests with getAppWebsite tests
- Remove tests for deleted utility functions
- All remaining tests pass
This consolidation improves performance by ensuring JSON.parse() is called
at most once per event, regardless of how many metadata fields are accessed.
* feat: use app name in window titles for NIP-89 app events
Add special handling for kind 31990 (Application Handler) events in
getEventDisplayTitle to use the app name from content JSON instead of
generic kind name. Falls back to identifier if app name not available.
This gives NIP-89 app handler events nice readable window titles.
---------
Co-authored-by: Claude <noreply@anthropic.com>