`, ``, proper headings) +- ARIA labels and roles (`role="feed"`, `aria-label` on actions) +- Keyboard navigation system (arrow keys, enter, escape) +- Focus management (modals, detail views) +- Screen reader testing and fixes +- Color contrast audit + +#### 3.4 Internationalization +**Priority**: Medium | **Effort**: Medium +**Files**: Setup i18n infrastructure, translate all components + +**Problem**: Hardcoded English strings, inconsistent locale usage + +**Solution**: +- i18next integration +- Extract all hardcoded strings +- Locale-aware number/date formatting (zap amounts, timestamps) +- Kind name translations +- RTL support improvements (related to existing RTL TODO) + +#### 3.5 Composable Renderer System +**Priority**: Medium | **Effort**: High +**Files**: Refactor complex renderers + +**Problem**: Renderers are monolithic, hard to reuse pieces + +**Solution**: Break into smaller components +- Content components (primary payload display) +- Metadata components (structured data display) +- Relationship components (connections/replies) +- Action components (user interactions) +- Enable mix-and-match composition diff --git a/claudedocs/event-rendering-system-analysis.md b/claudedocs/event-rendering-system-analysis.md new file mode 100644 index 0000000..8f8b92a --- /dev/null +++ b/claudedocs/event-rendering-system-analysis.md @@ -0,0 +1,1127 @@ +# Event Rendering System - Comprehensive Analysis & Improvement Plan + +**Date**: 2025-12-11 +**Context**: Grimoire Nostr Protocol Explorer +**Scope**: Deep architectural analysis of event rendering system covering 150+ registered event kinds with ~20 custom renderers + +--- + +## Executive Summary + +The current event rendering system has a **solid foundation** with good architectural patterns (registry-based routing, component reuse, type safety), but suffers from **inconsistencies in application** and **missing abstractions** that limit scalability, maintainability, and extensibility. + +**Key Findings:** +- ✅ **Strengths**: Registry pattern, BaseEventContainer, applesauce integration, type safety +- ❌ **Critical Issues**: Hardcoded detail renderers, inconsistent depth tracking, no error boundaries, missing threading abstraction +- 🎯 **Opportunity**: Transform from "working prototype" to "production-grade framework" with systematic improvements + +--- + +## Part 1: Current State Analysis + +### Architecture Overview + +``` +Current System Layers: +┌─────────────────────────────────────┐ +│ Renderer Layer │ Kind1Renderer, Kind6Renderer, etc. +│ (~20 custom, 130+ using default) │ +├─────────────────────────────────────┤ +│ Component Layer │ BaseEventContainer, EventAuthor, EventMenu +│ (Reusable UI components) │ RichText, EmbeddedEvent, MediaEmbed +├─────────────────────────────────────┤ +│ Registry Layer │ kindRenderers map, KindRenderer router +│ (Routing & fallback) │ DefaultKindRenderer +├─────────────────────────────────────┤ +│ Data Layer │ EventStore (applesauce), useNostrEvent hook +│ (Reactive state) │ RelayPool, Dexie cache +└─────────────────────────────────────┘ +``` + +### Event Kind Categories + +Analysis of 150+ registered kinds reveals **7 fundamental patterns**: + +1. **Content-Primary** (1, 30023, 9802) + - Main payload in `content` field + - Rich text rendering, markdown, media embeds + - Examples: Notes, articles, highlights + +2. **Reference Events** (6, 7, 9735) + - Point to other events via e/a tags + - Embed referenced content + - Examples: Reposts, reactions, zaps + +3. **Metadata Events** (0, 3, 10002) + - Structured data in content JSON + - Key-value pairs, lists, configurations + - Examples: Profiles, contacts, relay lists + +4. **List Events** (30000-39999 replaceable) + - Arrays of items in tags + - Follow sets, mute lists, bookmarks + - Addressable/replaceable nature + +5. **Media Events** (20, 21, 22, 1063) + - Content is URLs with metadata + - Images, videos, files + - Thumbnails, dimensions, MIME types + +6. **Action Events** (5, 1984) + - Represent operations on other events + - Deletions, reports, moderation + - Usually invisible to end users + +7. **Communication Events** (4, 14, 1111) + - Threaded messaging + - DMs, comments, chat messages + - Multiple threading models (NIP-10, NIP-22, NIP-28) + +--- + +## Part 2: What's Common to All Events + +### Universal Requirements + +Every event, regardless of kind, needs: + +1. **Author Context** - WHO created this + - Profile info (name, avatar, NIP-05) + - Clickable to open profile + - Badge/verification indicators + +2. **Temporal Context** - WHEN was this created + - Relative timestamps ("2h ago") + - Absolute time on hover (ISO format) + - Locale-aware formatting + +3. **Event Identity** - WHAT is this + - Kind badge with icon and name + - Event ID (bech32 format: nevent/naddr) + - Copy/share capabilities + +4. **Actions** - User operations + - Open in detail view + - Copy event ID + - View raw JSON + - (Future: Reply, React, Zap, Share) + +5. **Relay Context** - WHERE was this seen + - List of relays that served the event + - Relay health indicators + - Relay preferences for publishing + +6. **Addressability** - HOW to reference + - Regular events: nevent (id + relays + author) + - Addressable events: naddr (kind + pubkey + identifier + relays) + - note1 (deprecated but still supported) + +### Current Implementation + +**Well-Handled:** +- ✅ Author, Temporal, Identity, Actions (1-4) via `BaseEventContainer` + `EventMenu` +- ✅ Addressability (6) logic in EventDetailViewer + +**Missing Universally:** +- ❌ Signature verification indicator +- ❌ Edit history (NIP-09 deletion event tracking) +- ❌ Engagement preview (reply count, zap total, reaction summary) +- ❌ Related events indicator +- ❌ Community/context badges (NIP-72 communities, NIP-29 groups) + +**Recommendation:** Extend `BaseEventContainer` with optional engagement footer and verification indicator. + +--- + +## Part 3: Rendering Context Analysis + +### Three Primary Contexts + +1. **Feed/Timeline** - Compact, scannable view + - Emphasis on density, quick scanning + - Show summary/preview, not full content + - Inline media thumbnails + - Minimal interaction chrome + +2. **Detail** - Expansive, full-content view + - Emphasis on readability, completeness + - Full markdown rendering, full-size media + - Show relationships (replies, zaps, reactions) + - Additional metadata and actions + +3. **Embedded** - Nested preview within another event + - Context-aware depth limiting + - Minimal chrome (no duplicate headers if already in context) + - Click to expand/navigate + - Performance-conscious (lazy load) + +### Current Implementation + +**Feed Rendering:** +- ✅ Works well with `KindRenderer` + `BaseEventContainer` +- ✅ Consistent pattern across all kinds +- ⚠️ No virtualization for performance + +**Detail Rendering:** +- ❌ **CRITICAL**: Hardcoded switch statement in `EventDetailViewer.tsx`: + ```tsx + event.kind === kinds.Metadata ? + : event.kind === kinds.Contacts ? + : event.kind === kinds.LongFormArticle ? + : + ``` +- ❌ Breaks registry pattern - not extensible +- ❌ Only 5 kinds have detail renderers, rest fallback to feed + +**Embedded Rendering:** +- ⚠️ Uses same as feed (via `EmbeddedEvent` → `KindRenderer`) +- ⚠️ No context awareness +- ⚠️ Depth tracking inconsistent + +### Recommended Architecture + +**Unified Registry Pattern:** +```tsx +// Proposed structure +export const kindRenderers: KindRendererRegistry = { + 1: { + feed: Kind1Renderer, + detail: Kind1DetailRenderer, // optional, fallback to feed + embed: Kind1EmbedRenderer, // optional, fallback to feed + }, + // Or simplified: + 1: Kind1Renderer, // if no variants needed + 30023: { + feed: Kind30023Renderer, // Compact: title + summary + detail: Kind30023DetailRenderer, // Full markdown + relationships + } +}; + +// Usage +function KindRenderer({ event, context = 'feed' }) { + const registry = kindRenderers[event.kind]; + const Renderer = registry?.[context] || registry?.feed || registry || DefaultKindRenderer; + return ; +} +``` + +**Benefits:** +- ✅ Consistent pattern for all contexts +- ✅ Extensible - add detail renderers without modifying router +- ✅ Self-documenting - registry shows available variants +- ✅ Type-safe - validate registry at compile time + +--- + +## Part 4: Depth Tracking & Nesting + +### The Problem + +Events can reference other events infinitely: +- Kind 6 (repost) of Kind 6 of Kind 6... → infinite loop +- Kind 1 (note) replying to Kind 1 replying to Kind 1... → deep nesting +- Kind 9735 (zap) of article containing zaps... → exponential expansion + +### Current State + +- ✅ `Kind1Renderer` passes `depth` to `RichText` +- ✅ `RichText` uses depth to limit nesting +- ❌ `Kind6Renderer` (repost) doesn't track depth → infinite loop possible +- ❌ `Kind9735Renderer` (zap) embeds without depth → can nest infinitely +- ❌ `EmbeddedEvent` doesn't auto-increment depth + +### Solution: Systematic Depth Management + +```tsx +// 1. Universal depth constant +export const MAX_EMBED_DEPTH = 3; + +// 2. All renderers receive and honor depth +export interface BaseEventProps { + event: NostrEvent; + depth?: number; + context?: 'feed' | 'detail' | 'embed'; +} + +// 3. EmbeddedEvent auto-increments +export function EmbeddedEvent({ eventId, depth = 0, ...props }) { + const event = useNostrEvent(eventId); + if (!event) return ; + + if (depth >= MAX_EMBED_DEPTH) { + return ; + } + + return ; +} + +// 4. Depth-aware rendering +export function Kind6Renderer({ event, depth = 0 }) { + if (depth >= MAX_EMBED_DEPTH) { + return + Repost of + ; + } + + return + Reposted + + ; +} +``` + +**Benefits:** +- ✅ Prevents infinite loops +- ✅ Improves performance (limits cascade fetching) +- ✅ Better UX (collapsed deep threads with expand option) +- ✅ Consistent behavior across all renderers + +--- + +## Part 5: Threading & Reply Abstraction + +### The Challenge + +Multiple threading models exist in Nostr: + +1. **NIP-10** (Kind 1 notes) + - `e` tags with markers: `["e", id, relay, "root"|"reply"]` + - Root = original post, Reply = immediate parent + - Mentions = other referenced events + +2. **NIP-22** (Kind 1111 comments) + - **Uppercase tags** = root scope: `K`, `E`, `A`, `I`, `P` + - **Lowercase tags** = parent item: `k`, `e`, `a`, `i`, `p` + - Can thread on events OR external identifiers (URLs, podcasts, etc.) + - MUST NOT reply to kind 1 notes (use kind 1 instead) + +3. **NIP-28** (Kind 42 channel messages) + - Replies within channel context + - Different tag structure + +4. **NIP-29** (Kinds 10, 11, 12 group messages) + - Group-specific threading + - Additional permissions layer + +### Current Implementation + +- ✅ Kind1Renderer shows NIP-10 reply indicator +- ✅ Uses `getNip10References` from applesauce +- ❌ No support for NIP-22 (Kind 1111 not implemented) +- ❌ No support for other threading models +- ❌ No generic threading components + +### Proposed Abstraction + +**Helper Layer:** +```tsx +// src/lib/threading.ts +export interface ThreadReference { + type: 'nip10' | 'nip22' | 'nip28' | 'nip29'; + root?: EventPointer | AddressPointer | string; // string for external (NIP-22) + parent?: EventPointer | AddressPointer | string; + mentions?: Array; + rootAuthor?: string; + parentAuthor?: string; +} + +export function getThreadReferences(event: NostrEvent): ThreadReference | null { + // Detect threading model by kind and tags + if (event.kind === 1) return getNip10Thread(event); + if (event.kind === 1111) return getNip22Thread(event); + if (event.kind === 42) return getNip28Thread(event); + // ... etc + return null; +} +``` + +**Component Layer:** +```tsx +// Generic thread indicator +export function ThreadIndicator({ event, depth = 0 }) { + const refs = getThreadReferences(event); + if (!refs) return null; + + const parentEvent = useNostrEvent(refs.parent); + + return ( + + + Replying to + {parentEvent ? ( + + ) : refs.type === 'nip22' && typeof refs.parent === 'string' ? ( + + ) : ( + + )} + + ); +} + +// Generic thread tree (for detail view) +export function ThreadTree({ rootEvent }) { + const replies = useReplies(rootEvent); + return ( + + {replies.map(reply => ( + + ))} + + ); +} +``` + +**Benefits:** +- ✅ Single component works across all threading models +- ✅ Extensible to new NIPs +- ✅ Reusable across different renderers +- ✅ Consistent UX for users +- ✅ Easier to maintain (one place to fix threading bugs) + +--- + +## Part 6: Metadata Extraction Patterns + +### Current Approaches + +1. **Applesauce Helpers** ✅ (GOOD) + - `getArticleTitle`, `getZapAmount`, `getNip10References` + - Well-tested, consistent, handles edge cases + - Examples: `Kind30023Renderer`, `Kind9735Renderer` + +2. **Manual Tag Parsing** ⚠️ (INCONSISTENT) + - `event.tags.find(t => t[0] === "e")` + - Error-prone, repeated code, misses edge cases + - Examples: `Kind6Renderer`, various places + +3. **JSON Parsing** ❌ (ERROR-PRONE) + - `JSON.parse(event.content)` without try/catch + - Can crash entire app if malformed + - Examples: Profile metadata, relay lists + +### What Applesauce Provides + +Currently has helpers for: +- ✅ Articles (30023): title, summary, published, image +- ✅ Zaps (9735): amount, sender, request, pointers +- ✅ Threading (1): NIP-10 references +- ✅ Profiles (0): metadata parsing +- ✅ Relays: seen relays, relay hints + +### What's Missing + +Need helpers for: +- ❌ File metadata (1063): url, hash, size, mime, dimensions +- ❌ Media events (20, 21, 22): URLs, thumbnails, dimensions +- ❌ List events (30000+): systematic list item extraction +- ❌ Comments (1111): NIP-22 uppercase/lowercase tag parsing +- ❌ Reactions (7): emoji normalization (+ → ❤️) +- ❌ Reposts (6, 16, 18): reposted event extraction +- ❌ Highlights (9802): context, highlight text +- ❌ Calendar events (31922-31925): date/time parsing +- ❌ Polls (1068): options, votes, tally +- ❌ Communities (34550): community info extraction + +### Recommendation + +**Architecture Principle:** Renderers should NEVER parse tags/content directly. + +```tsx +// BAD ❌ +const eTag = event.tags.find(t => t[0] === "e")?.[1]; + +// GOOD ✅ +import { getRepostedEvent } from '@/lib/helpers/repost'; +const repostPointer = getRepostedEvent(event); +``` + +**Action Items:** +1. Contribute missing helpers to applesauce-core (if generic) +2. Create local helper library for Grimoire-specific needs +3. Audit all renderers, replace manual parsing with helpers +4. Enforce via ESLint rule: no direct `event.tags.find` + +--- + +## Part 7: Performance & Scalability + +### Current Bottlenecks + +1. **No Virtualization** + - All events in feed render immediately + - 1000 events = 1000 DOM nodes = slow scroll + - Wastes memory on off-screen content + +2. **No Memoization** + - RichText parses content on every render + - Profile lookups happen repeatedly + - JSON.parse re-runs unnecessarily + - Expensive computations not cached + +3. **No Lazy Loading** + - All renderer code loaded upfront + - ~20 renderer components = large initial bundle + - Could code-split by kind + +4. **Heavy Base Components** + - Every event has `BaseEventContainer` overhead + - Profile fetch for every `EventAuthor` + - Could batch profile fetches + +5. **Cascading Fetches** + - Embedded event triggers fetch + - That event might embed another + - Exponential growth without depth limiting + +### Good News + +- ✅ EventStore handles deduplication +- ✅ Dexie provides offline caching +- ✅ Reactive system (RxJS) is efficient + +### Solutions + +**1. Virtual Scrolling** +```tsx +import { Virtuoso } from 'react-virtuoso'; + +function EventFeed({ events }) { + return ( + ( + + )} + /> + ); +} +``` + +**2. Memoization** +```tsx +// Wrap all renderers +export const Kind1Renderer = React.memo(({ event, depth }) => { + const refs = useMemo(() => getNip10References(event), [event.id]); + const handleClick = useCallback(() => {...}, [event.id]); + + return + + ; +}); +``` + +**3. Code Splitting** +```tsx +// Lazy load detail renderers +const Kind30023DetailRenderer = lazy(() => + import('./kinds/Kind30023DetailRenderer') +); + +// Use with Suspense +}> + + +``` + +**4. Batch Profile Fetches** +```tsx +// Instead of individual useProfile in every EventAuthor +// Batch load all visible profiles +function EventFeed({ events }) { + const pubkeys = useMemo(() => + events.map(e => e.pubkey), [events] + ); + useBatchProfiles(pubkeys); // Prefetch + + return events.map(e => ); +} +``` + +**Performance Targets:** +- Feed with 10,000 events: Smooth 60fps scroll +- Initial render: < 100ms +- Event interaction: < 50ms response +- Bundle size: < 300KB for core, lazy load rest + +--- + +## Part 8: Error Handling & Resilience + +### Current Error Scenarios + +1. **Malformed Events** + - Invalid JSON in content + - Missing required tags + - Incorrect tag structure + +2. **Network Failures** + - Relays timeout + - Event not found + - Incomplete data + +3. **Parsing Failures** + - Markdown rendering errors + - NIP-19 decode failures + - Media load failures + +4. **Rendering Errors** + - Component crashes + - Infinite loops (depth issue) + - Out of memory + +### Current Handling + +- ⚠️ Some try/catch in parsers (inconsistent) +- ⚠️ EmbeddedEvent shows "Loading..." forever if fetch fails +- ❌ No error boundaries around renderers +- ✅ DefaultKindRenderer for unknown kinds (good!) + +### Solution: Error Boundaries + +```tsx +// Per-event error boundary +export function EventErrorBoundary({ children, event }) { + return ( + ( + + + + Failed to render event + + Kind {event.kind} • {event.id.slice(0, 8)} + + + Error details + {error.message} + + + + Retry + viewJson(event)}>View JSON + reportIssue(event, error)}>Report + + + )} + > + {children} + + ); +} + +// Usage in feed +{events.map(event => ( + + + +))} +``` + +**Benefits:** +- ✅ One broken event doesn't break entire feed +- ✅ User gets actionable error info +- ✅ Developer gets diagnostics +- ✅ Graceful degradation + +--- + +## Part 9: Accessibility & Internationalization + +### Accessibility Gaps + +**Keyboard Navigation:** +- ❌ No keyboard shortcuts for common actions +- ❌ Can't navigate between events with Tab +- ❌ Can't expand/collapse without mouse + +**Screen Reader Support:** +- ❌ EventMenu has no aria-label +- ❌ Embedded events don't announce properly +- ❌ Time stamps are "2h ago" but no absolute time for SR +- ⚠️ BaseEventContainer uses `` not `` + +**Visual:** +- ⚠️ Muted text might not meet WCAG AA contrast +- ❌ No prefers-reduced-motion support +- ❌ Focus indicators inconsistent + +**RTL Support:** +- ❌ Noted in TODO as partially implemented +- ❌ Inline elements conflict with RTL alignment + +### I18n Gaps + +- ⚠️ Timestamps use locale from state but inconsistently +- ❌ Number formatting hardcoded to "en" (zap amounts) +- ❌ Kind names are English-only strings +- ❌ Error messages hardcoded English +- ❌ No language detection for content + +### Solutions + +**Semantic HTML:** +```tsx +export function BaseEventContainer({ event, children }) { + return ( + + + + + {relativeTime} + + + + {children} + + ); +} +``` + +**Keyboard Navigation:** +```tsx +// Arrow keys to navigate events +// Enter to open detail +// Escape to close +// Tab to focus actions +useKeyboardNavigation({ + onUp: () => focusPrevEvent(), + onDown: () => focusNextEvent(), + onEnter: () => openEventDetail(), +}); +``` + +**I18n:** +```tsx +import { useTranslation } from 'react-i18next'; + +export function EventMenu({ event }) { + const { t } = useTranslation(); + return ( + + {t('event.actions.copy_id')} + + ); +} +``` + +--- + +## Part 10: Developer Experience + +### Current DX + +**Good:** +- ✅ Clear file structure (`src/components/nostr/kinds/`) +- ✅ TypeScript types (`BaseEventProps`) +- ✅ README documenting pattern +- ✅ Consistent naming (`KindXRenderer`) + +**Friction:** +- ❌ Can't hot-reload new renderer without modifying `index.tsx` +- ❌ No component gallery (Storybook) +- ❌ Hard to test renderers in isolation +- ❌ Manual registration in multiple places +- ❌ No development tooling (event inspector) +- ❌ No renderer generator CLI + +### Ideal DX + +**1. Convention-Based Registration** +```bash +# Just create the file, auto-discovered +src/components/nostr/kinds/Kind1111Renderer.tsx +# No need to modify index.tsx +``` + +**2. Component Gallery** +```tsx +// Visit /dev/renderers in dev mode +// Browse all renderers with sample events +// Test with different contexts (feed/detail/embed) +// Inspect props, performance +``` + +**3. Testing Utilities** +```tsx +import { renderKind, mockEvent } from '@/test/utils'; + +test('Kind1Renderer displays content', () => { + const event = mockEvent({ kind: 1, content: 'Hello' }); + const { getByText } = renderKind(1, event); + expect(getByText('Hello')).toBeInTheDocument(); +}); +``` + +**4. Generator CLI** +```bash +npm run generate:renderer -- --kind 1111 --nip 22 +# Scaffolds: +# - Kind1111Renderer.tsx with boilerplate +# - Kind1111Renderer.test.tsx +# - Updates registry +# - Adds to documentation +``` + +**5. Dev Tools** +```tsx +// Browser extension or dev panel + + + +// Shows: props, state, performance, helper calls, errors +``` + +--- + +## Part 11: What's Working Well (To Preserve) + +These patterns are **strengths** to maintain and enhance: + +1. ✅ **Registry Pattern**: Centralized kind → renderer mapping +2. ✅ **BaseEventContainer**: Consistent header/footer +3. ✅ **Applesauce Integration**: Using library helpers +4. ✅ **Type Safety**: TypeScript interfaces +5. ✅ **Separation of Concerns**: Rendering separate from data fetching +6. ✅ **Recursive Rendering**: KindRenderer can nest +7. ✅ **Universal Actions**: EventMenu available everywhere +8. ✅ **Event Identity**: Good handling of regular vs addressable +9. ✅ **Default Fallback**: Unknown kinds still display +10. ✅ **Component Reuse**: EmbeddedEvent, MediaEmbed, RichText + +**Don't throw away these foundations - build on them!** + +--- + +## Part 12: Comprehensive Improvement Roadmap + +### Phase 1: Foundation Fixes (1-2 weeks) +**Goal:** Fix critical architectural issues and quick wins + +**1.1 Unified Detail Renderer Registry** +- Remove hardcoded switch in EventDetailViewer +- Create `detailRenderers` map parallel to `kindRenderers` +- Fallback logic: detail → feed → default +- Files: `src/components/nostr/kinds/index.tsx`, `EventDetailViewer.tsx` +- **Impact:** HIGH | **Effort:** LOW + +**1.2 Systematic Depth Tracking** +- Add `MAX_EMBED_DEPTH` constant +- Update `BaseEventProps` to require depth +- Audit all renderers using `EmbeddedEvent` +- Implement `CollapsedPreview` for max depth +- Files: All `*Renderer.tsx` files +- **Impact:** HIGH | **Effort:** MEDIUM + +**1.3 Error Boundaries** +- Create `EventErrorBoundary` component +- Wrap all events in feeds +- Add diagnostic error cards +- File: `src/components/EventErrorBoundary.tsx` +- **Impact:** HIGH | **Effort:** LOW + +**1.4 Fix JSON Viewer Scrolling** +- From TODO: "JSON viewer scrolling" +- Add `overflow-auto` and `max-height` to JSON container +- File: `src/components/JsonViewer.tsx` +- **Impact:** MEDIUM | **Effort:** TRIVIAL + +**1.5 Renderer Memoization** +- Wrap all renderer components with `React.memo` +- Add `useMemo` for expensive computations +- Add `useCallback` for handlers +- Files: All `*Renderer.tsx` files +- **Impact:** MEDIUM | **Effort:** LOW + +**Deliverables:** +- [ ] Detail renderer registry implemented +- [ ] All renderers honor depth (with tests) +- [ ] Error boundaries deployed +- [ ] JSON viewer scrolls properly +- [ ] All renderers memoized + +--- + +### Phase 2: Component Library (2-3 weeks) +**Goal:** Build reusable abstractions for common patterns + +**2.1 Generic Threading Components** +- `getThreadReferences()` helper supporting NIP-10, NIP-22, NIP-28 +- `` component +- `` for parent preview +- `` for detail view reply chains +- Files: `src/lib/threading.ts`, `src/components/Thread/` +- **Impact:** HIGH | **Effort:** HIGH + +**2.2 NIP-22 Comment Support** +- Implement `Kind1111Renderer` (from TODO) +- NIP-22 tag parsing helpers (K/k, E/e, A/a, I/i, P/p) +- External identifier display (I tags) +- Nested comment threading +- Files: `src/lib/helpers/nip22.ts`, `src/components/nostr/kinds/Kind1111Renderer.tsx` +- **Impact:** HIGH | **Effort:** HIGH + +**2.3 Relationship Panels** +- `` - Show replies to event +- `` - Show zaps with total/list +- `` - Group reactions by emoji +- `` - Universal engagement indicators +- Use in detail renderers +- Files: `src/components/nostr/Relationships/` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**2.4 Enhanced Media Components** +- Multi-stage rendering (placeholder → thumbnail → full → error) +- Lazy loading with IntersectionObserver +- NSFW blur with content-warning tag support +- Quality selection for videos +- Accessibility improvements (alt text, captions) +- Files: Enhance `src/components/nostr/MediaEmbed.tsx` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**2.5 Context-Aware Rendering** +- Add `context` prop to BaseEventProps +- Renderers adapt to feed vs detail vs embed +- Update all existing renderers +- Files: `src/components/nostr/kinds/index.tsx`, all renderers +- **Impact:** MEDIUM | **Effort:** LOW + +**Deliverables:** +- [ ] Threading works across NIP-10, NIP-22, NIP-28 +- [ ] Kind 1111 (comments) fully functional +- [ ] Detail views show relationships +- [ ] Media rendering has all stages +- [ ] Context awareness implemented + +--- + +### Phase 3: Architecture Evolution (3-4 weeks) +**Goal:** Transform into production-grade framework + +**3.1 Performance Optimization** +- Virtual scrolling with react-virtuoso +- Code splitting for detail renderers +- Batch profile fetching +- Suspense boundaries +- Performance monitoring +- Files: `src/components/ReqViewer.tsx`, `EventDetailViewer.tsx` +- **Impact:** HIGH | **Effort:** MEDIUM + +**3.2 Helper Library Expansion** +- Audit all renderers for manual tag parsing +- Create helpers for all missing NIPs: + - File metadata (1063) + - Media events (20, 21, 22) + - Lists (30000+) + - Reposts (6, 16, 18) + - Highlights (9802) + - Calendar (31922-31925) + - Polls (1068) +- Submit generic ones to applesauce-core +- Files: `src/lib/helpers/` directory structure +- **Impact:** HIGH | **Effort:** HIGH + +**3.3 Accessibility Improvements** +- Semantic HTML (``, ``, proper headings) +- ARIA labels and roles +- Keyboard navigation system +- Focus management +- Screen reader testing and fixes +- WCAG AA compliance audit +- Files: All renderers, BaseEventContainer +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.4 Internationalization** +- i18next integration +- Extract all hardcoded strings +- Locale-aware number/date formatting +- Kind name translations +- RTL support improvements +- Files: Setup i18n infrastructure, translate all components +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.5 Composable Renderer System** +- Break renderers into smaller components: + - Content components (primary payload) + - Metadata components (structured data) + - Relationship components (connections) + - Action components (interactions) +- Enable mix-and-match composition +- Files: Refactor all complex renderers +- **Impact:** MEDIUM | **Effort:** HIGH + +**Deliverables:** +- [ ] Smooth 60fps scroll with 10K events +- [ ] All NIPs have helper functions +- [ ] WCAG AA compliant +- [ ] Multi-language support +- [ ] Composable renderer architecture + +--- + +### Phase 4: Developer Experience (2-3 weeks) +**Goal:** Make development delightful and efficient + +**4.1 Component Gallery (Storybook)** +- Setup Storybook +- Create stories for all renderers +- Mock event generator +- Interactive playground +- Visual regression testing +- Files: `.storybook/`, `src/components/nostr/kinds/*.stories.tsx` +- **Impact:** HIGH | **Effort:** MEDIUM + +**4.2 Testing Infrastructure** +- Test utilities: `renderKind()`, `mockEvent()` +- Unit tests for all helpers +- Integration tests for renderers +- E2E tests for common flows +- Coverage targets (>80%) +- Files: `src/test/`, `*.test.tsx` for all renderers +- **Impact:** HIGH | **Effort:** HIGH + +**4.3 Generator CLI** +- `generate:renderer` command +- Scaffolds: renderer, tests, types +- Auto-updates registry +- Generates documentation stub +- Files: `scripts/generate-renderer.ts` +- **Impact:** MEDIUM | **Effort:** LOW + +**4.4 Development Tools** +- Event inspector dev panel +- Performance profiler +- Helper call tracer +- Error diagnostic viewer +- Files: `src/dev-tools/` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**4.5 Documentation** +- Architecture guide (this document as living docs) +- Renderer patterns guide +- Helper function reference +- Contribution guide +- API documentation (TypeDoc) +- Files: `docs/` directory +- **Impact:** HIGH | **Effort:** MEDIUM + +**Deliverables:** +- [ ] Storybook with all renderers +- [ ] >80% test coverage +- [ ] Renderer generator working +- [ ] Dev tools panel functional +- [ ] Comprehensive documentation + +--- + +## Part 13: Success Metrics + +**Phase 1 Success:** +- Zero infinite loop bugs +- <1% event rendering errors in production +- Detail renderers added without modifying router + +**Phase 2 Success:** +- NIP-22 comments working end-to-end +- Detail views show full relationship context +- All threading models supported + +**Phase 3 Success:** +- 10K event feed scrolls at 60fps +- Zero manual tag parsing in renderers +- WCAG AA accessibility audit passes + +**Phase 4 Success:** +- New renderer takes <30min to scaffold +- >80% test coverage maintained +- Storybook has 100% renderer coverage + +**Overall Success:** +- Contributors can add renderers without asking questions +- Users report high quality, responsive UI +- Grimoire becomes reference implementation for Nostr clients + +--- + +## Part 14: Priority Decision Matrix + +**Immediate (Week 1-2):** +1. Detail renderer registry fix +2. Depth tracking safety +3. Error boundaries +4. JSON viewer scroll fix + +**Short-term (Week 3-6):** +1. NIP-22 comment support (user request in TODO) +2. Threading abstraction +3. Memoization & performance basics +4. Relationship panels + +**Medium-term (Week 7-12):** +1. Virtual scrolling +2. Helper library expansion +3. Accessibility improvements +4. Component gallery + +**Long-term (Month 4+):** +1. Plugin architecture +2. Advanced dev tools +3. Full i18n +4. Composable system evolution + +--- + +## Part 15: Risk Assessment + +**Technical Risks:** +- 🟡 **Breaking changes**: Depth prop changes might break existing renderers + - *Mitigation:* Make depth optional with default 0, gradual rollout +- 🟡 **Performance regression**: Memoization might increase memory + - *Mitigation:* Monitor metrics, iterate based on data +- 🟢 **Compatibility**: Changes to BaseEventProps might affect community code + - *Mitigation:* Keep backward compatibility, deprecate gradually + +**Resource Risks:** +- 🟡 **Time**: 10-12 weeks of focused work + - *Mitigation:* Phased approach, can ship incrementally +- 🟢 **Expertise**: Some NIPs are complex (NIP-22, NIP-29) + - *Mitigation:* Study specifications, prototype early + +**User Impact:** +- 🟢 **Disruption**: Most changes are internal improvements +- 🟢 **Testing**: Can test thoroughly in staging before production +- 🟢 **Rollback**: Registry pattern makes rollback easy (swap renderers) + +--- + +## Conclusion + +The Grimoire event rendering system has **excellent foundations** but needs **systematic improvements** to scale from prototype to production. + +**The path forward:** +1. ✅ **Preserve** what works (registry, base components, type safety) +2. 🔧 **Fix** critical issues (detail registry, depth tracking, error handling) +3. 🏗️ **Build** missing abstractions (threading, relationships, helpers) +4. ⚡ **Optimize** performance (virtualization, memoization, lazy loading) +5. 🎨 **Polish** UX (accessibility, i18n, media rendering) +6. 🛠️ **Empower** developers (tooling, testing, documentation) + +**This roadmap transforms the system from "working" to "world-class" in ~3 months** with measurable success criteria and manageable risk. + +The result will be a **reference implementation** that other Nostr clients can learn from and contribute to. + +--- + +**Next Steps:** +1. Review this analysis with team/community +2. Prioritize phases based on user feedback +3. Create GitHub issues/project board from roadmap +4. Begin Phase 1 implementation +5. Update TODO.md with prioritized items + +**Questions for Discussion:** +- Which Phase 1 items are most critical? +- Should we tackle NIP-22 (comments) in Phase 1 given TODO mention? +- What's the community appetite for contributing to applesauce helpers? +- Performance targets: 10K events reasonable or aim higher/lower? +- Should we build plugin architecture in Phase 3 or defer?
` + +**Visual:** +- ⚠️ Muted text might not meet WCAG AA contrast +- ❌ No prefers-reduced-motion support +- ❌ Focus indicators inconsistent + +**RTL Support:** +- ❌ Noted in TODO as partially implemented +- ❌ Inline elements conflict with RTL alignment + +### I18n Gaps + +- ⚠️ Timestamps use locale from state but inconsistently +- ❌ Number formatting hardcoded to "en" (zap amounts) +- ❌ Kind names are English-only strings +- ❌ Error messages hardcoded English +- ❌ No language detection for content + +### Solutions + +**Semantic HTML:** +```tsx +export function BaseEventContainer({ event, children }) { + return ( + + + + + {relativeTime} + + + + {children} + + ); +} +``` + +**Keyboard Navigation:** +```tsx +// Arrow keys to navigate events +// Enter to open detail +// Escape to close +// Tab to focus actions +useKeyboardNavigation({ + onUp: () => focusPrevEvent(), + onDown: () => focusNextEvent(), + onEnter: () => openEventDetail(), +}); +``` + +**I18n:** +```tsx +import { useTranslation } from 'react-i18next'; + +export function EventMenu({ event }) { + const { t } = useTranslation(); + return ( + + {t('event.actions.copy_id')} + + ); +} +``` + +--- + +## Part 10: Developer Experience + +### Current DX + +**Good:** +- ✅ Clear file structure (`src/components/nostr/kinds/`) +- ✅ TypeScript types (`BaseEventProps`) +- ✅ README documenting pattern +- ✅ Consistent naming (`KindXRenderer`) + +**Friction:** +- ❌ Can't hot-reload new renderer without modifying `index.tsx` +- ❌ No component gallery (Storybook) +- ❌ Hard to test renderers in isolation +- ❌ Manual registration in multiple places +- ❌ No development tooling (event inspector) +- ❌ No renderer generator CLI + +### Ideal DX + +**1. Convention-Based Registration** +```bash +# Just create the file, auto-discovered +src/components/nostr/kinds/Kind1111Renderer.tsx +# No need to modify index.tsx +``` + +**2. Component Gallery** +```tsx +// Visit /dev/renderers in dev mode +// Browse all renderers with sample events +// Test with different contexts (feed/detail/embed) +// Inspect props, performance +``` + +**3. Testing Utilities** +```tsx +import { renderKind, mockEvent } from '@/test/utils'; + +test('Kind1Renderer displays content', () => { + const event = mockEvent({ kind: 1, content: 'Hello' }); + const { getByText } = renderKind(1, event); + expect(getByText('Hello')).toBeInTheDocument(); +}); +``` + +**4. Generator CLI** +```bash +npm run generate:renderer -- --kind 1111 --nip 22 +# Scaffolds: +# - Kind1111Renderer.tsx with boilerplate +# - Kind1111Renderer.test.tsx +# - Updates registry +# - Adds to documentation +``` + +**5. Dev Tools** +```tsx +// Browser extension or dev panel + + + +// Shows: props, state, performance, helper calls, errors +``` + +--- + +## Part 11: What's Working Well (To Preserve) + +These patterns are **strengths** to maintain and enhance: + +1. ✅ **Registry Pattern**: Centralized kind → renderer mapping +2. ✅ **BaseEventContainer**: Consistent header/footer +3. ✅ **Applesauce Integration**: Using library helpers +4. ✅ **Type Safety**: TypeScript interfaces +5. ✅ **Separation of Concerns**: Rendering separate from data fetching +6. ✅ **Recursive Rendering**: KindRenderer can nest +7. ✅ **Universal Actions**: EventMenu available everywhere +8. ✅ **Event Identity**: Good handling of regular vs addressable +9. ✅ **Default Fallback**: Unknown kinds still display +10. ✅ **Component Reuse**: EmbeddedEvent, MediaEmbed, RichText + +**Don't throw away these foundations - build on them!** + +--- + +## Part 12: Comprehensive Improvement Roadmap + +### Phase 1: Foundation Fixes (1-2 weeks) +**Goal:** Fix critical architectural issues and quick wins + +**1.1 Unified Detail Renderer Registry** +- Remove hardcoded switch in EventDetailViewer +- Create `detailRenderers` map parallel to `kindRenderers` +- Fallback logic: detail → feed → default +- Files: `src/components/nostr/kinds/index.tsx`, `EventDetailViewer.tsx` +- **Impact:** HIGH | **Effort:** LOW + +**1.2 Systematic Depth Tracking** +- Add `MAX_EMBED_DEPTH` constant +- Update `BaseEventProps` to require depth +- Audit all renderers using `EmbeddedEvent` +- Implement `CollapsedPreview` for max depth +- Files: All `*Renderer.tsx` files +- **Impact:** HIGH | **Effort:** MEDIUM + +**1.3 Error Boundaries** +- Create `EventErrorBoundary` component +- Wrap all events in feeds +- Add diagnostic error cards +- File: `src/components/EventErrorBoundary.tsx` +- **Impact:** HIGH | **Effort:** LOW + +**1.4 Fix JSON Viewer Scrolling** +- From TODO: "JSON viewer scrolling" +- Add `overflow-auto` and `max-height` to JSON container +- File: `src/components/JsonViewer.tsx` +- **Impact:** MEDIUM | **Effort:** TRIVIAL + +**1.5 Renderer Memoization** +- Wrap all renderer components with `React.memo` +- Add `useMemo` for expensive computations +- Add `useCallback` for handlers +- Files: All `*Renderer.tsx` files +- **Impact:** MEDIUM | **Effort:** LOW + +**Deliverables:** +- [ ] Detail renderer registry implemented +- [ ] All renderers honor depth (with tests) +- [ ] Error boundaries deployed +- [ ] JSON viewer scrolls properly +- [ ] All renderers memoized + +--- + +### Phase 2: Component Library (2-3 weeks) +**Goal:** Build reusable abstractions for common patterns + +**2.1 Generic Threading Components** +- `getThreadReferences()` helper supporting NIP-10, NIP-22, NIP-28 +- `` component +- `` for parent preview +- `` for detail view reply chains +- Files: `src/lib/threading.ts`, `src/components/Thread/` +- **Impact:** HIGH | **Effort:** HIGH + +**2.2 NIP-22 Comment Support** +- Implement `Kind1111Renderer` (from TODO) +- NIP-22 tag parsing helpers (K/k, E/e, A/a, I/i, P/p) +- External identifier display (I tags) +- Nested comment threading +- Files: `src/lib/helpers/nip22.ts`, `src/components/nostr/kinds/Kind1111Renderer.tsx` +- **Impact:** HIGH | **Effort:** HIGH + +**2.3 Relationship Panels** +- `` - Show replies to event +- `` - Show zaps with total/list +- `` - Group reactions by emoji +- `` - Universal engagement indicators +- Use in detail renderers +- Files: `src/components/nostr/Relationships/` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**2.4 Enhanced Media Components** +- Multi-stage rendering (placeholder → thumbnail → full → error) +- Lazy loading with IntersectionObserver +- NSFW blur with content-warning tag support +- Quality selection for videos +- Accessibility improvements (alt text, captions) +- Files: Enhance `src/components/nostr/MediaEmbed.tsx` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**2.5 Context-Aware Rendering** +- Add `context` prop to BaseEventProps +- Renderers adapt to feed vs detail vs embed +- Update all existing renderers +- Files: `src/components/nostr/kinds/index.tsx`, all renderers +- **Impact:** MEDIUM | **Effort:** LOW + +**Deliverables:** +- [ ] Threading works across NIP-10, NIP-22, NIP-28 +- [ ] Kind 1111 (comments) fully functional +- [ ] Detail views show relationships +- [ ] Media rendering has all stages +- [ ] Context awareness implemented + +--- + +### Phase 3: Architecture Evolution (3-4 weeks) +**Goal:** Transform into production-grade framework + +**3.1 Performance Optimization** +- Virtual scrolling with react-virtuoso +- Code splitting for detail renderers +- Batch profile fetching +- Suspense boundaries +- Performance monitoring +- Files: `src/components/ReqViewer.tsx`, `EventDetailViewer.tsx` +- **Impact:** HIGH | **Effort:** MEDIUM + +**3.2 Helper Library Expansion** +- Audit all renderers for manual tag parsing +- Create helpers for all missing NIPs: + - File metadata (1063) + - Media events (20, 21, 22) + - Lists (30000+) + - Reposts (6, 16, 18) + - Highlights (9802) + - Calendar (31922-31925) + - Polls (1068) +- Submit generic ones to applesauce-core +- Files: `src/lib/helpers/` directory structure +- **Impact:** HIGH | **Effort:** HIGH + +**3.3 Accessibility Improvements** +- Semantic HTML (``, ``, proper headings) +- ARIA labels and roles +- Keyboard navigation system +- Focus management +- Screen reader testing and fixes +- WCAG AA compliance audit +- Files: All renderers, BaseEventContainer +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.4 Internationalization** +- i18next integration +- Extract all hardcoded strings +- Locale-aware number/date formatting +- Kind name translations +- RTL support improvements +- Files: Setup i18n infrastructure, translate all components +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.5 Composable Renderer System** +- Break renderers into smaller components: + - Content components (primary payload) + - Metadata components (structured data) + - Relationship components (connections) + - Action components (interactions) +- Enable mix-and-match composition +- Files: Refactor all complex renderers +- **Impact:** MEDIUM | **Effort:** HIGH + +**Deliverables:** +- [ ] Smooth 60fps scroll with 10K events +- [ ] All NIPs have helper functions +- [ ] WCAG AA compliant +- [ ] Multi-language support +- [ ] Composable renderer architecture + +--- + +### Phase 4: Developer Experience (2-3 weeks) +**Goal:** Make development delightful and efficient + +**4.1 Component Gallery (Storybook)** +- Setup Storybook +- Create stories for all renderers +- Mock event generator +- Interactive playground +- Visual regression testing +- Files: `.storybook/`, `src/components/nostr/kinds/*.stories.tsx` +- **Impact:** HIGH | **Effort:** MEDIUM + +**4.2 Testing Infrastructure** +- Test utilities: `renderKind()`, `mockEvent()` +- Unit tests for all helpers +- Integration tests for renderers +- E2E tests for common flows +- Coverage targets (>80%) +- Files: `src/test/`, `*.test.tsx` for all renderers +- **Impact:** HIGH | **Effort:** HIGH + +**4.3 Generator CLI** +- `generate:renderer` command +- Scaffolds: renderer, tests, types +- Auto-updates registry +- Generates documentation stub +- Files: `scripts/generate-renderer.ts` +- **Impact:** MEDIUM | **Effort:** LOW + +**4.4 Development Tools** +- Event inspector dev panel +- Performance profiler +- Helper call tracer +- Error diagnostic viewer +- Files: `src/dev-tools/` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**4.5 Documentation** +- Architecture guide (this document as living docs) +- Renderer patterns guide +- Helper function reference +- Contribution guide +- API documentation (TypeDoc) +- Files: `docs/` directory +- **Impact:** HIGH | **Effort:** MEDIUM + +**Deliverables:** +- [ ] Storybook with all renderers +- [ ] >80% test coverage +- [ ] Renderer generator working +- [ ] Dev tools panel functional +- [ ] Comprehensive documentation + +--- + +## Part 13: Success Metrics + +**Phase 1 Success:** +- Zero infinite loop bugs +- <1% event rendering errors in production +- Detail renderers added without modifying router + +**Phase 2 Success:** +- NIP-22 comments working end-to-end +- Detail views show full relationship context +- All threading models supported + +**Phase 3 Success:** +- 10K event feed scrolls at 60fps +- Zero manual tag parsing in renderers +- WCAG AA accessibility audit passes + +**Phase 4 Success:** +- New renderer takes <30min to scaffold +- >80% test coverage maintained +- Storybook has 100% renderer coverage + +**Overall Success:** +- Contributors can add renderers without asking questions +- Users report high quality, responsive UI +- Grimoire becomes reference implementation for Nostr clients + +--- + +## Part 14: Priority Decision Matrix + +**Immediate (Week 1-2):** +1. Detail renderer registry fix +2. Depth tracking safety +3. Error boundaries +4. JSON viewer scroll fix + +**Short-term (Week 3-6):** +1. NIP-22 comment support (user request in TODO) +2. Threading abstraction +3. Memoization & performance basics +4. Relationship panels + +**Medium-term (Week 7-12):** +1. Virtual scrolling +2. Helper library expansion +3. Accessibility improvements +4. Component gallery + +**Long-term (Month 4+):** +1. Plugin architecture +2. Advanced dev tools +3. Full i18n +4. Composable system evolution + +--- + +## Part 15: Risk Assessment + +**Technical Risks:** +- 🟡 **Breaking changes**: Depth prop changes might break existing renderers + - *Mitigation:* Make depth optional with default 0, gradual rollout +- 🟡 **Performance regression**: Memoization might increase memory + - *Mitigation:* Monitor metrics, iterate based on data +- 🟢 **Compatibility**: Changes to BaseEventProps might affect community code + - *Mitigation:* Keep backward compatibility, deprecate gradually + +**Resource Risks:** +- 🟡 **Time**: 10-12 weeks of focused work + - *Mitigation:* Phased approach, can ship incrementally +- 🟢 **Expertise**: Some NIPs are complex (NIP-22, NIP-29) + - *Mitigation:* Study specifications, prototype early + +**User Impact:** +- 🟢 **Disruption**: Most changes are internal improvements +- 🟢 **Testing**: Can test thoroughly in staging before production +- 🟢 **Rollback**: Registry pattern makes rollback easy (swap renderers) + +--- + +## Conclusion + +The Grimoire event rendering system has **excellent foundations** but needs **systematic improvements** to scale from prototype to production. + +**The path forward:** +1. ✅ **Preserve** what works (registry, base components, type safety) +2. 🔧 **Fix** critical issues (detail registry, depth tracking, error handling) +3. 🏗️ **Build** missing abstractions (threading, relationships, helpers) +4. ⚡ **Optimize** performance (virtualization, memoization, lazy loading) +5. 🎨 **Polish** UX (accessibility, i18n, media rendering) +6. 🛠️ **Empower** developers (tooling, testing, documentation) + +**This roadmap transforms the system from "working" to "world-class" in ~3 months** with measurable success criteria and manageable risk. + +The result will be a **reference implementation** that other Nostr clients can learn from and contribute to. + +--- + +**Next Steps:** +1. Review this analysis with team/community +2. Prioritize phases based on user feedback +3. Create GitHub issues/project board from roadmap +4. Begin Phase 1 implementation +5. Update TODO.md with prioritized items + +**Questions for Discussion:** +- Which Phase 1 items are most critical? +- Should we tackle NIP-22 (comments) in Phase 1 given TODO mention? +- What's the community appetite for contributing to applesauce helpers? +- Performance targets: 10K events reasonable or aim higher/lower? +- Should we build plugin architecture in Phase 3 or defer?
`, ``, proper headings) +- ARIA labels and roles +- Keyboard navigation system +- Focus management +- Screen reader testing and fixes +- WCAG AA compliance audit +- Files: All renderers, BaseEventContainer +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.4 Internationalization** +- i18next integration +- Extract all hardcoded strings +- Locale-aware number/date formatting +- Kind name translations +- RTL support improvements +- Files: Setup i18n infrastructure, translate all components +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**3.5 Composable Renderer System** +- Break renderers into smaller components: + - Content components (primary payload) + - Metadata components (structured data) + - Relationship components (connections) + - Action components (interactions) +- Enable mix-and-match composition +- Files: Refactor all complex renderers +- **Impact:** MEDIUM | **Effort:** HIGH + +**Deliverables:** +- [ ] Smooth 60fps scroll with 10K events +- [ ] All NIPs have helper functions +- [ ] WCAG AA compliant +- [ ] Multi-language support +- [ ] Composable renderer architecture + +--- + +### Phase 4: Developer Experience (2-3 weeks) +**Goal:** Make development delightful and efficient + +**4.1 Component Gallery (Storybook)** +- Setup Storybook +- Create stories for all renderers +- Mock event generator +- Interactive playground +- Visual regression testing +- Files: `.storybook/`, `src/components/nostr/kinds/*.stories.tsx` +- **Impact:** HIGH | **Effort:** MEDIUM + +**4.2 Testing Infrastructure** +- Test utilities: `renderKind()`, `mockEvent()` +- Unit tests for all helpers +- Integration tests for renderers +- E2E tests for common flows +- Coverage targets (>80%) +- Files: `src/test/`, `*.test.tsx` for all renderers +- **Impact:** HIGH | **Effort:** HIGH + +**4.3 Generator CLI** +- `generate:renderer` command +- Scaffolds: renderer, tests, types +- Auto-updates registry +- Generates documentation stub +- Files: `scripts/generate-renderer.ts` +- **Impact:** MEDIUM | **Effort:** LOW + +**4.4 Development Tools** +- Event inspector dev panel +- Performance profiler +- Helper call tracer +- Error diagnostic viewer +- Files: `src/dev-tools/` +- **Impact:** MEDIUM | **Effort:** MEDIUM + +**4.5 Documentation** +- Architecture guide (this document as living docs) +- Renderer patterns guide +- Helper function reference +- Contribution guide +- API documentation (TypeDoc) +- Files: `docs/` directory +- **Impact:** HIGH | **Effort:** MEDIUM + +**Deliverables:** +- [ ] Storybook with all renderers +- [ ] >80% test coverage +- [ ] Renderer generator working +- [ ] Dev tools panel functional +- [ ] Comprehensive documentation + +--- + +## Part 13: Success Metrics + +**Phase 1 Success:** +- Zero infinite loop bugs +- <1% event rendering errors in production +- Detail renderers added without modifying router + +**Phase 2 Success:** +- NIP-22 comments working end-to-end +- Detail views show full relationship context +- All threading models supported + +**Phase 3 Success:** +- 10K event feed scrolls at 60fps +- Zero manual tag parsing in renderers +- WCAG AA accessibility audit passes + +**Phase 4 Success:** +- New renderer takes <30min to scaffold +- >80% test coverage maintained +- Storybook has 100% renderer coverage + +**Overall Success:** +- Contributors can add renderers without asking questions +- Users report high quality, responsive UI +- Grimoire becomes reference implementation for Nostr clients + +--- + +## Part 14: Priority Decision Matrix + +**Immediate (Week 1-2):** +1. Detail renderer registry fix +2. Depth tracking safety +3. Error boundaries +4. JSON viewer scroll fix + +**Short-term (Week 3-6):** +1. NIP-22 comment support (user request in TODO) +2. Threading abstraction +3. Memoization & performance basics +4. Relationship panels + +**Medium-term (Week 7-12):** +1. Virtual scrolling +2. Helper library expansion +3. Accessibility improvements +4. Component gallery + +**Long-term (Month 4+):** +1. Plugin architecture +2. Advanced dev tools +3. Full i18n +4. Composable system evolution + +--- + +## Part 15: Risk Assessment + +**Technical Risks:** +- 🟡 **Breaking changes**: Depth prop changes might break existing renderers + - *Mitigation:* Make depth optional with default 0, gradual rollout +- 🟡 **Performance regression**: Memoization might increase memory + - *Mitigation:* Monitor metrics, iterate based on data +- 🟢 **Compatibility**: Changes to BaseEventProps might affect community code + - *Mitigation:* Keep backward compatibility, deprecate gradually + +**Resource Risks:** +- 🟡 **Time**: 10-12 weeks of focused work + - *Mitigation:* Phased approach, can ship incrementally +- 🟢 **Expertise**: Some NIPs are complex (NIP-22, NIP-29) + - *Mitigation:* Study specifications, prototype early + +**User Impact:** +- 🟢 **Disruption**: Most changes are internal improvements +- 🟢 **Testing**: Can test thoroughly in staging before production +- 🟢 **Rollback**: Registry pattern makes rollback easy (swap renderers) + +--- + +## Conclusion + +The Grimoire event rendering system has **excellent foundations** but needs **systematic improvements** to scale from prototype to production. + +**The path forward:** +1. ✅ **Preserve** what works (registry, base components, type safety) +2. 🔧 **Fix** critical issues (detail registry, depth tracking, error handling) +3. 🏗️ **Build** missing abstractions (threading, relationships, helpers) +4. ⚡ **Optimize** performance (virtualization, memoization, lazy loading) +5. 🎨 **Polish** UX (accessibility, i18n, media rendering) +6. 🛠️ **Empower** developers (tooling, testing, documentation) + +**This roadmap transforms the system from "working" to "world-class" in ~3 months** with measurable success criteria and manageable risk. + +The result will be a **reference implementation** that other Nostr clients can learn from and contribute to. + +--- + +**Next Steps:** +1. Review this analysis with team/community +2. Prioritize phases based on user feedback +3. Create GitHub issues/project board from roadmap +4. Begin Phase 1 implementation +5. Update TODO.md with prioritized items + +**Questions for Discussion:** +- Which Phase 1 items are most critical? +- Should we tackle NIP-22 (comments) in Phase 1 given TODO mention? +- What's the community appetite for contributing to applesauce helpers? +- Performance targets: 10K events reasonable or aim higher/lower? +- Should we build plugin architecture in Phase 3 or defer?