Expose COMMIT_SHA and COMMIT_TAG via import.meta.env at build time.
In CI, these come from GitLab env vars; locally they fall back to git.
The changelog page now shows:
- A pre-release banner when the build is untagged, with a link to
the GitLab diff between the latest release and main
- An external link icon on each version card header linking to the
GitLab release page for that version
- 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)
- Hide original highlights by adding opacity=0 inside blobbi-eye groups
- Inject sad highlights INTO blobbi-eye groups so they track with pupil movement
- Sad highlights now move with eye tracking and participate in blinking
- Blue water fill stays as overlay (on eye white, doesn't need tracking)
- Slow tears: duration 6s with 3s pause between cycles
- Alternating tear mode: tears switch sides each cycle (no flickering)
- Only affects SAD emotion, angry/neutral unchanged
- Position blue water shape relative to eye white (not pupil center)
- Water now sits at bottom of eye white like pooled tears
- Reposition highlights: upper (larger) and lower (smaller) with clear separation
- Upper highlight at cy - radius*0.55, lower at cy + radius*0.35
- Only affects SAD emotion (generateSadEyeEffects), angry unchanged
- Lower sad mouth position by adding Y offset based on curve amount
- Fix sad eye highlights: larger top-left, smaller right-side
- Change blue watery fill to proper lower 1/3 semicircle shape using path
- Fix baby eye detection to match gradient fills (url(#...Pupil...))
- Swap sad/angry eyebrow angles: sad now worried (/\), angry now aggressive (\/)
- Replace mouth safely using regex-only approach (no section slicing)
- Update dev panel to label default as 'Default' with happy emoji
- Add EmotionDevContext and BlobbiEmotionPanel for dev-only emotion testing
- Create emotions.ts with configurable emotion overlays (sad, happy, angry, surprised, sleepy)
- Use deterministic tear selection (hash-based) to prevent flickering
- Add marker-based SVG detection with regex fallback for mouth/eye elements
- Update visual components to pass emotion prop through hierarchy
- Add SVG comment markers to all Blobbi base SVGs for reliable element detection
- LetterEditor: replace stickyHeader/headerLeft with renderToolbar render prop;
callers decide where to place the tool buttons
- Both ComposeLetterSheet and LetterPreferencesSection: use SubHeaderBar noArc
+ useLayoutOptions({ hasSubHeader: true }) so tools sit in the sticky sub-header
matching every other tabbed/sub-header page in the app
- Extract FabButton from FloatingComposeButton (avatar shape mask + primary bg)
- FloatingComposeButton now delegates to FabButton
- ComposeLetterSheet: replace inline send button with FabButton FAB,
fixed bottom-right on mobile, sticky in column on desktop
- Remove separate page-level send button from compose header
- useLetterPreferences: simplify to just expose raw saved prefs + isThemeDefault flag,
no longer conflates theme stationery with saved stationery
- LetterPreferencesSection: always pull from useThemeStationery directly when
isThemeDefault, persist only on explicit user picks (handleSetStationery),
sync preview live when theme changes
- ComposeLetterSheet: same pattern — init from themeStationery, switch to saved
pref once settings load, track explicit user picks to avoid theme override
- LetterEditor drawer: remove bg-background / rounded-b-3xl / border-b card shape
- ComposeLetterSheet: use themeStationery immediately (no parchment fallback),
switch to saved pref once encrypted settings load, sync with theme changes
- ComposeLetterSheet: move send button to inline flow below the card (no more fixed overlay)
- LetterPreferencesPage: remove PageHeader — back button + title now live inside
LetterEditor's headerLeft slot, eliminating the double bar
- Port letter protocol (kind 8211, NIP-44 encrypted) from lief
- LettersPage at /letters with inbox and sent tabs
- ComposeLetterSheet with full stationery, font, frame, sticker, drawing support
- LetterCard with expand-to-read animation and deletion
- LetterPreferencesSection stored in encrypted settings (NIP-78)
- /settings/letters route for letter preferences
- Letters added to sidebar nav
- All letter lib utilities: letterTypes, letterUtils, colorUtils extensions, sanitizeSvg, svgDrawing
- StationeryBackground, StationeryPicker, FramePicker, StickerPicker, DrawingCanvas all ported
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.