- Add accent-text and zap-text tokens to all 7 themes for proper contrast
on accent/zap-colored buttons (fixes white-on-light-accent in Catppuccin,
Nord Frost, Hackerman, Sepia, Gruvbox)
- Replace text-white → text-accent-text on all accent buttons (20+ instances)
- Replace text-white → text-zap-text on zap buttons
- Replace hover:text-white → hover:text-accent-text on follow/action buttons
- Replace bg-blue-500 → bg-accent in FountainCard (theme-aware)
- Remaining text-white is correct: overlays on bg-black, danger badges
- Replace clickable divs with semantic <button> elements (NoteCard, SearchView)
- Add role="dialog", aria-modal, aria-labelledby on all modals (Login, Quote, Zap, Lightbox)
- Add role="presentation" on overlay backdrops (NoteCard menu, emoji pickers)
- Add aria-label to all icon-only buttons (close, nav arrows, context menu)
- Add aria-expanded to context menu toggle
- Add meaningful alt text to all 35+ images (avatars, covers, thumbnails, media)
- Add aria-label to form inputs (search, onboarding login)
Malformed profiles with non-string fields (e.g. nip05: {}) crashed
React's entire render tree in production. Add typeof guards and
profileName() utility across all components that render profile data.
Add ErrorBoundary in main.tsx to show crash details instead of blank screen.
Override NDK default outbox relays (purplepag.es DNS failure was stalling
getZapInfo), add 45s zap timeout, disable outbox on NWC instance, fix
follower notification dedup in poller. Zap history rows now show a
clickable preview of the original zapped note.
Global feed now uses a persistent live subscription (closeOnEose: false)
so new notes stream in real-time instead of requiring manual refresh.
Inspired by Wisp's streaming architecture.
Every fetchEvents call across the entire codebase now uses
fetchWithTimeout with groupable: false — prevents NDK from
batching/reusing stale subscriptions. This fixes Articles, DMs,
Notifications, Zaps, and Trending hanging indefinitely.
Also adds since filters on global (2h) and follow (24h) feeds
to ensure relay freshness, and fixes ArticleFeed re-fetch bug
where follows changes wiped latest tab results.
- fetchZapsReceived: kind 9735 filtered by #p tag (receipts)
- fetchZapsSent: kind 9734 filtered by authors (zap requests)
- ZapHistoryView: Received / Sent tabs with row count; header shows
total sats in/out; each row: avatar, amount, counterpart name
(clickable → profile), comment, time ago
- Receipt parsing: amount from embedded zap request in "description"
tag (millisats → sats); sender from uppercase "P" tag with fallback
to zap request pubkey
- Request parsing: amount from "amount" tag, recipient from "p" tag
- ⚡ zaps nav item added to sidebar between search and relays
- Logged-out fallback state with prompt to log in
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>