- Remove standalone website link from main profile bio area
- Prepend website as a "Website" field entry in the fields list
- Add inline ProfileFieldInline component for mobile view (xl:hidden)
- Website now appears alongside other profile fields in the sidebar (desktop) and inline below bio (mobile)
- Special rendering for $BTC fields with orange Bitcoin icon and truncated address
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Address and copy icon on one line as a clickable row
- Address truncates with ellipsis, copy icon stays visible
- Whole row is clickable to copy, shows check on success
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Show full address with break-all instead of truncating
- Full-width "Copy address" button below the address
- Prevents the copy button from being clipped by modal overflow
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Media tiles now link to the source event (nevent) instead of opening the raw image
- Favicons try /favicon.ico first, then fall back to /favicon.svg
- Add explicit image-rendering: auto to fix crispy/aliased thumbnails
- Data model now tracks eventId + authorPubkey per media item
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Tighten media grid gap from 1.5 to 0.5 for closer tiles
- Remove sizes="96px" hint that was causing pixelated/crispy image rendering
- Switch favicons from Google service to direct /favicon.ico from each domain
- Remove rounded-sm background styling from favicon images
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Media grid items now have individual rounded-lg corners with gap spacing
- Images use sizes hint for better quality rendering at small sizes
- Streak indicator: flat style with filled flame icon using theme accent color,
positioned between username and description, 24h window, kind 1 only
- Profile field URLs now show Google favicon next to each link with graceful fallback
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Add Zap button to profile header (visible for other users with lightning address)
- Add posting streak counter with flame icon (36h window, caps at 99+)
- Create ProfileRightSidebar with Media grid and Profile Fields sections
- Handle $BTC profile field with copiable address, QR code modal, and mempool.space link
- Regular profile fields render as labels with linked URLs
- MainLayout now accepts optional custom right sidebar prop
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Add IntersectionObserver to both VideoPlayer (used in note cards) and
VineMedia (used in vine feed cards) to automatically pause playback
when less than 25% of the video container is visible in the viewport.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This reverts the codebase back to the state at commit 5babdf6.
Reverted 2 commit(s):
- 64e1273: Race relays on first EOSE with grace timer for remaining
- cf193ab: Route reads to a single relay (round-robin) for fast EOSE resolution
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Replace the round-robin single-relay approach with proper racing:
- Queries are sent to ALL read relays simultaneously
- First relay to return EOSE starts a 1.5s grace timer
- Remaining relays that respond within the grace window have their
events merged into the result set
- If all relays finish before the timer, returns immediately
- Events are deduplicated via NSet (handles replaceable events correctly)
- Publishing and req() still delegate to the pool unchanged
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Previously reqRouter sent every query to all 3 read relays, meaning
NPool.query() had to wait for all relays to coordinate before resolving.
The slowest relay dictated the feed speed.
Now reads go to one relay at a time, rotating round-robin across the
configured read relays. Each query resolves as soon as that single relay
sends EOSE — no waiting on the other two. Publishing still fans out to
all write relays.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Add `enabled` parameter to `useTrendingTags` and `useLatestAccounts` hooks
- RightSidebar now detects xl breakpoint visibility with matchMedia
- Sidebar queries only fire after the feed finishes its initial fetch
- On smaller screens where the sidebar is hidden, queries are skipped entirely
- Gives the feed full relay bandwidth priority on page load
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Rewrite useFeed to use useInfiniteQuery with timestamp-based pagination
- Reduce page size from 60/40 to 30 for both follows and global tabs
- Add intersection observer sentinel in Feed component for auto-loading
- Deduplicate feed items across pages
- Show spinner while fetching next page
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Feed NoteCardSkeleton: restructured to match NoteCard's avatar + stacked
name/handle header with full-width content below (was incorrectly nested)
- VinesPage VineSkeleton: restructured to match vine card layout with
header, title, video placeholder, hashtags, and actions
- SearchPage PostSkeleton: aligned with Feed skeleton for consistency
- NoteCard: show skeleton for avatar and name while useAuthor is loading,
resolves to real data or fallback when relay responds/gives up
- RepostHeader: skeleton for reposter name while author loads
- ReplyContext: skeleton for reply-to name while author loads
- PostDetailPage: skeleton for author row in both main post and parent note
- EmbeddedNote: skeleton for author row in embedded note card
- EmbeddedNaddr: skeleton for author row in embedded naddr card
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Feed.tsx: initialize activeTab to 'follows' when user is logged in, 'global' otherwise
- useFeed.ts: filter out events with created_at > now in both follows and global feeds, including embedded repost content and fetched originals
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Moved volume toggle to the right of the play/pause button
- Progress bar fill and scrub dot now use bg-primary accent color
- Replaced Maximize icon with Expand (lucide) for fullscreen button
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Created a reusable VideoPlayer component with custom controls:
- Big centered play button overlay before first play
- Bottom control bar with gradient background that auto-hides during playback
- Play/pause toggle, seek bar with hover scrub dot, current/total time display
- Volume mute toggle and fullscreen button
- Controls reappear on mouse move and auto-hide after 2.5s
- Used in both NoteCard and PostDetailPage
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Extract video URLs (.mp4, .webm, .mov) from note content
- Parse all imeta tags into a URL-keyed map to get thumbnails for videos
- NoteCard renders videos with the same play/pause UI as vine events,
using imeta thumbnail as the poster image
- PostDetailPage also renders videos with the same player
- Videos are already stripped from NoteContent text by the MEDIA_URL_REGEX
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
The whitespace collapsing logic was stripping newlines before naddr-embed
tokens that have a URL, causing text and the URL to smash together.
Now only pure block embeds (no URL) trim preceding whitespace.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- NoteContent now shows the original URL as a clickable link above the
embedded naddr card when the naddr was extracted from a regular URL
- Replaced "Addressable event view coming soon" placeholder in NIP19Page
with a full AddrDetailPage that shows hero image, author, title,
description, image gallery, metadata fields, and tags
- AddrDetailPage extracts metadata from both event tags and JSON content
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Added useAddrEvent hook for fetching addressable events by kind+pubkey+d-tag
- Created EmbeddedNaddr component that displays title, description, image, and author
from addressable events (extracting metadata from tags and JSON content)
- Updated NoteContent to detect naddr1 identifiers in regular URLs (e.g.
bitpopart.com/art/naddr1...) and render them as Nostr embeds
- Added naddr1 to the nostr: URI regex so nostr:naddr1... is also handled
- Added naddr-embed token type with proper whitespace collapsing
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Updated useFeed hook to query kinds [1, 6] for the follows tab
- Reposts are resolved from embedded content JSON or fetched by event ID
- Added FeedItem type with repostedBy and sortTimestamp fields
- Deduplication prefers direct posts over reposts of the same event
- NoteCard now shows a "reposted by" header with the reposter's name
- Feed renders repost items with unique keys
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Changed `lg:border-r` to `xl:border-r` on the main content area across
all 12 pages so the right border only appears when the right sidebar is
visible (at xl/1280px+).
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
The right sidebar was showing at lg (1024px) which made the three-column
layout too cramped. Changed from `hidden lg:flex` to `hidden xl:flex` so
the sidebar only appears when there's enough horizontal space.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
When viewing a reply's post detail page, the event being replied to
is now rendered above the main post with a thread connector line.
- Added getParentEventId() helper that extracts the parent event ID
from e-tags following NIP-10 conventions (marked and positional)
- Added ParentNote component with avatar, author info, content preview,
and a vertical thread connector line linking parent to child
- Parent note is clickable and navigates to its own post detail page
- Includes skeleton loading state while parent event is being fetched
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
- Add All/Mentions tab bar with underline indicator
- Like notifications: show heart icon + actor name + original post with full content, images, link previews, and action buttons
- Repost notifications: show repost icon + actor name + original post
- Zap notifications: show zap icon + actor name + amount + original post
- Mention notifications: show @ icon + actor name + full note card with avatar, nip05, reply context, content, and action buttons
- Fetch referenced events for likes/reposts/zaps to show the original post
- Include reply, repost, react, zap, and more action buttons on all notification posts
- Skeleton loading states matching the new layout
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Display name on first line (bold), @handle · timestamp on second
line (muted), matching the Ditto-style two-line author layout.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
Restructure NoteCard so avatar+name is a header row, and all
content (text, images, videos, action buttons) renders at full
card width below it — no more indentation from the avatar column.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>