Introduce ExternalPostData as a shared shape that both useBlueskyPost
and the new useMastodonPost hook normalize into. Both BlueskyEmbed and
MastodonEmbed are now thin wrappers that fetch data from their respective
APIs and render via the shared ExternalPostCard component.
MastodonEmbed now fetches from the instance's public API instead of
using an iframe, matching the native card treatment already applied to
Bluesky. Both embeds have built-in /i/ navigation so the DiscussBar
is no longer rendered for them.
Clicking the card body navigates to /i/{postUrl} instead of opening
bsky.app externally. Avatar and display name are separately clickable
buttons that navigate to /i/{profileUrl}.
Fetch post data from the public Bluesky API (getPostThread) and render
it natively with avatar, display name, handle, text content, images,
external link thumbnails, and interaction stats (replies, reposts, likes).
This eliminates the iframe dependency on embed.bsky.app and provides a
more consistent look matching the existing EmbeddedNote style.
- Remove status from NoteCard (no longer shown inline next to author
names in the feed)
- Add status as a speech bubble beside the avatar on profile pages,
with a small triangular tail pointing toward the avatar
- Add status to ProfileHoverCard below the bio section
- Widen profile status bubble to 280/360px for longer statuses
- Remove SmilePlus emoji icon from status editor trigger in sidebar
and mobile drawer
Wall posts are filtered by the profile owner's follow list, so posts
from non-followed users wouldn't show up anyway. This hides the compose
box, FAB button, and shows a contextual message instead.
Resolve merge conflicts in 5 files, keeping both NIP-38 user statuses
and music/podcasts/events features from main:
- src/App.tsx
- src/contexts/AppContext.ts
- src/lib/extraKinds.ts
- src/lib/schemas.ts
- src/test/TestApp.tsx
Resolve conflicts in AppRouter, NoteCard, sidebarItems, and PostDetailPage
by keeping both music/podcast features and main's additions (books,
calendar events).
The trending endpoint returned massive payloads with no field filtering support.
The search API with sort=readinglog and fields parameter returns slim responses
in under a second while still showing genuinely popular books.
Register kind 30315 in extraKinds as a feedOnly entry with showKey
(not feedKey) so statuses appear as a toggle in Other Stuff > Social
but are NOT included in the main feed query. The toggle controls
whether statuses are displayed on NoteCard author rows and profile
pages.
- extraKinds: registered with showKey='showUserStatuses', feedOnly=true
- ContentSettings: handle feedOnly entries with showKey as display toggles
- NoteCard: gate useUserStatus behind feedSettings.showUserStatuses
- ProfilePage: gate status display behind feedSettings.showUserStatuses
- Defaults: showUserStatuses=true (enabled by default)
- Add /books page displaying popular books fetched from OpenLibrary's trending API
- Add Books entry to sidebar registry so users can add it from the More menu
- Add /books route to AppRouter
- Show book title instead of raw 'isbn:...' in comment context by fetching book info via useBookInfo hook
Implement reading, displaying, and publishing NIP-38 general statuses:
Hooks:
- useUserStatus: query kind 30315 (d='general') for a pubkey, handles
NIP-40 expiration and empty-content clearing
- usePublishStatus: publish/clear kind 30315 via useNostrPublish
Display:
- ProfilePage: status shown below NIP-05 badge, clickable if it has
an r-tag URL
- NoteCard: compact inline status after author name, separated by dot,
truncated to 120px, italic muted text
Editing:
- LeftSidebar popover: inline status editor between user profile and
account switcher — tap 'Set a status' to expand input, Save/Clear/
Cancel controls, Enter to submit, Escape to cancel
- MobileDrawer: same inline editor between account section and nav
Status is NOT shown on the bottom-left avatar trigger button or mobile
drawer user row — only inside the opened menu.
Country suggestion only appears at the top of search results when
the query is an exact match on name or code. For prefix matches
(e.g. 'angol' -> Angola), the country appears below profile results.
If there are no profile results, the country is shown at the top.
Typing a country name in the search bar now shows matching countries
with their flag emoji, navigating to /i/iso3166:<CODE> on click.
Works on both desktop (ProfileSearchDropdown) and mobile
(MobileSearchSheet) with full keyboard navigation support.
Browse all countries in a searchable grid. Clicking a flag navigates
to the existing /i/iso3166:<CODE> external content page. The World
item is also registered in the sidebar so users can add it via the
More menu.
- Remove CustomEmojiPicker.tsx and useUserEmojiPacks.ts (replaced by
Derek's useCustomEmojis + emoji-mart custom categories)
- Update EmojiPackContent to use local kind 10030 query
- Update EmojiShortcodeAutocomplete to use useCustomEmojis
- Fix quick reaction buttons to render custom emojis as images
- Fix quick reaction buttons to include emoji tag when reacting
- Filter stale custom emojis from quick reaction row
- Add emoji tags to compose box mock event for preview rendering