- Switch from CalVer (date+SHA) to semantic versioning starting at v2.0.0
- Create release skill (.agents/skills/release/) with full AI-guided release workflow
- Add CHANGELOG.md with initial 2.0.0 entry
- Update CI tag regex to match semver tags (v2.0.0 instead of v2026.03.24-sha)
- Extract changelog content into GitLab release descriptions
- Update Android versionName to 2.0.0 in build.gradle
- Update iOS MARKETING_VERSION to 2.0.0 in pbxproj
- Expose VERSION (semver) and BUILD_DATE (ISO 8601) as build-time constants
- Display version and build date in Settings page footer
- Remove npm release script (releases are now done via the AI skill)
Add 80px of invisible padding around the badge so the mouse starts
influencing the 3D tilt well before it reaches the image itself.
Negative margin compensates so the layout is unaffected. Glare
coordinates are remapped to the image area within the padded zone.
Mask the specular glare overlay to the badge image's own alpha
channel so effects only paint over visible pixels. Also remove
the hard-coded rounded-2xl and ring overlay that imposed an opaque
rectangular shape on transparent badge images.
Hovering the mouse across the badge image now rotates it in
perspective space with a specular glare overlay that tracks the
cursor, making the badge feel like a tangible, glossy object.
Introduces a reusable useCardTilt hook for pointer-driven 3D
perspective transforms with configurable max tilt and scale.
Apply the theme's title font to the DialogTitle in both the theme
builder dialog (ThemeSelector) and the Edit Profile Theme dialog
(ProfilePage), so users get a live preview of their chosen title
font in the dialog heading.
When no title font was explicitly set (undefined), published theme
events omitted the title font tag entirely. This happened easily
when users selected Inter as the title font (the default), which
toggled back to undefined due to the deselect behavior.
Now resolveThemeForPublishing falls back titleFont to the body font,
ensuring published events always include both font tags when a body
font is present.
The useApplyFonts hook in AppProvider only loaded body fonts
(activeConfig.font) but never loaded title fonts (activeConfig.titleFont).
The loadAndApplyTitleFont function and CSS variable --title-font-family
existed but were never called on startup/theme change, so components
referencing the variable always fell back to inherit.
Replace UserRow (profile link) with RepostRow (nevent link) in the
reposts tab so clicking a repost navigates to the repost event detail
view, matching the existing behavior for reactions.
- Render kind 6/16 repost events as standalone viewable cards (similar to
kind 7 reactions): compact activity-style card showing repost icon, author
avatar, author name, 'reposted' label, and timestamp
- Support both normal and threaded layouts for repost events in NoteCard
- Add repost detail view in PostDetailPage with full action buttons (reply,
repost, react, share, more) and ancestor thread pointing to reposted event
- Register kind 6/16 in all kind label registries: CommentContext KIND_ICONS,
extraKinds KIND_SPECIFIC_LABELS/ICONS, and shellTitleForKind
- Separate quotes count from reposts in action buttons: reposts button now
shows only repost count, new Quote button shows quote count separately
- Quote button on detail page opens InteractionsModal on the quotes tab
- Quote count sourced from useEventInteractions for accurate counts
(NIP-85 doesn't provide quote_cnt)
Use the --title-font-family CSS custom property on left sidebar
navigation labels and all right sidebar widget titles (Trends,
Hot Posts, New Accounts, Media, Profile fields). Falls back to
inherit when no title font is configured. Also removes the font
preview section from FontSection.
useFeedTab defaulted to 'ditto' when logged out, but pages like
Videos only accept ['follows', 'global'] as valid tabs. The 'ditto'
default was never validated against validTabs, so no feed query
matched and nothing loaded. Now the default is validated and falls
back to the last valid tab ('global') when it's not in the list.
Instead of a generic 'Same as body' placeholder, the title font
combobox now displays the body font's name (rendered in that font's
typeface) when no title font is explicitly set. Falls back to
'Default (Inter)' when neither font is set.
The title font combobox was showing 'Default (Inter)' when no title
font was set, but the actual fallback is the body font. Add a
placeholder prop to FontPicker and pass 'Same as body' from
FontSection for the title picker.
- Refactor FontPicker into a bare combobox (no section header, no
'quick brown fox' preview text)
- Add FontSection component that combines Body and Title font pickers
in a single section with inline labels and a live preview showing
both fonts in context (display name + body text)
- Title font falls back to the body font when not explicitly set, so
the profile display name inherits the theme's body font rather than
the default Inter
- Update ThemeSelector builder dialog and ProfilePage edit dialog to
use FontSection with controlled body/title font props
Embedded/quoted posts (EmbeddedNote, EmbeddedNaddr) no longer display
full image thumbnails. Instead, images are shown as a small icon+label
indicator at the bottom, consistent with how videos and audio are
already represented. This keeps compact views lightweight and focused
on text content.
Implement the title font feature across the full stack:
- Type system: Add titleFont to ThemeConfig, ThemePreset, ThemeDefinition,
ActiveProfileTheme interfaces and Zod schema
- Event encoding: Update f-tag build/parse to emit role markers (body/title)
with backward-compatible parsing of legacy roleless tags
- Font loading: Add loadAndApplyTitleFont with --title-font-family CSS var
- UI: Add Title Font picker to theme builder dialog and profile theme editor,
with configurable label prop on FontPicker
- Profile rendering: Apply --title-font-family to the display name h2
- Data flow: Thread titleFont through ThemeSelector snapshots, theme
presets, publish/update, NostrSync, ThemeContent, and diff detection
Add prose-code:text-foreground so inline code elements use the theme
foreground color instead of the typography plugin default (dark gray),
which was invisible against the muted background in dark mode.
The Tailwind Typography plugin sets bold/strong text to gray-900 by default,
which is invisible on dark backgrounds. Added prose-strong:text-foreground
and other theme-aware color overrides for list markers, blockquotes, rules,
and table headers across all markdown prose views.
Long unbreakable strings (sha256 hashes, URLs, base36 pubkeys) in NIP documents
and articles caused large word-spacing gaps in narrow containers. Added break-words,
horizontal scroll for code blocks, and consistent inline code styling to
CustomNipCard, ArticleContent, and PullRequestCard.
Port NostrURI module from Shakespeare to generate nostr:// clone URIs
from kind 30617 event data (pubkey, d-tag, relays). Display the Nostr
clone URI in GitRepoCard as the sole clone URL, replacing the previous
HTTPS clone URL. Also use the nostr:// URI for Shakespeare clone links.
The FAB background div always had rounded-full applied, which added
border-radius: 9999px even when an emoji mask was active. This caused
square (and other non-circular) avatar shapes to still appear rounded.
Now rounded-full is only applied when there is no emoji shape mask,
matching the pattern used by the Avatar component.
Sign kind 22242 AUTH events automatically when relays send challenges.
Uses a signer ref pattern so the pool doesn't need to be recreated
when the user logs in/out or switches accounts.
Remove gradient background and encryption footer from the full card, use
a clean bordered card with centered sender description. Add
EncryptedMessageCompact for quote posts, reply indicators, and the reply
composer — dispatched from EmbeddedNote like vanish events.
Kind 4 (NIP-04 encrypted DM) events were rendering their encrypted
content as plain text. Now they show a visual card with sender and
recipient avatars connected by a mail icon, with encryption type
detection (NIP-04 vs NIP-44) displayed in a footer badge with a lock icon.
Registered kind 4 across NoteCard, PostDetailPage, and CommentContext.
The fallthrough to EXTRA_KINDS produced plural/categorical labels like
'requests to vanish' and 'user statuses'. Now getKindLabel only uses
KIND_LABELS which has proper singular forms ('a request to vanish',
'a status'). Added missing entries for kinds 6, 16, 62, 30315.
- Themes use Sparkles (matching sidebar), not Palette (that's color moments)
- Profile badges now reads 'Commenting on profile badges by @Mary'
instead of 'Commenting on @Mary's profile badges'
CardsIcon for Magic decks, ChestIcon for geocaches/found logs,
Clapperboard for vines, Music for tracks/playlists, Camera for photos,
Film for videos, GitBranch for repos, GitPullRequest for PRs,
BookOpen for articles, Podcast for episodes/trailers, BarChart3 for polls,
PartyPopper for follow packs, Palette for color moments.
- Add kind-specific suffixes: badge, theme, follow pack, emoji pack, etc.
- Add kind-specific postfixes: apps show 'on Zapstore', releases show 'release'
- Profile badges (30008) show '@User's profile badges' with author hover card
- Add icons for all supported kinds (Award, Palette, Package, etc.)
- Add BookOpen icon inline next to book titles in ISBN context
- Add @ prefix to author names in reaction context
- Expand KIND_LABELS to cover all Ditto-supported kinds with proper articles
- IsbnCommentContext: Wrap book title link in HoverCard showing cover
thumbnail, title, and authors (reusing useBookInfo data)
- CountryCommentContext: New component extracted from ExternalCommentContext,
wraps country link in HoverCard showing flag, region/country label,
name, and parent country for subdivisions
- Both follow the same HoverCard pattern as UrlCommentContext
- EmbeddedNaddrCard: Add MaybeProfileHoverCard wrapper on avatar and
name links with disableHoverCards prop (matching EmbeddedNoteCard)
- NoteCard EventActionHeader: Wrap author name in ProfileHoverCard
- CommentContext: Wrap author links in ReplyToCommentContext,
ProfileCommentContext, and ReactionCommentContext
- LiveStreamPage ParticipantRow: Wrap avatar and name links
Add KIND_SPECIFIC_ICONS override map in extraKinds.ts so kinds in
extraFeedKinds arrays get their own icon instead of inheriting the
parent def's icon. Nsites (15128/35128) now show Globe, patches
show GitPullRequestArrow, etc.
Add getKindLabel() to extraKinds.ts as the canonical resolver for
per-kind labels. Kinds in extraFeedKinds (like nsites 15128/35128)
now show 'nsite' instead of the parent category 'development'.