Render kind 32267 software application events with app icon, name,
summary, platform badges, screenshots, and action buttons in both
feed (NoteCard) and detail (PostDetailPage) views. Add useAddrEvent
fallback to wss://relay.zapstore.dev for kinds 32267/30063 so app
events are discoverable even when not on the user's relay set.
When the weather API reports precipitation for a country, render a
canvas-based particle overlay: animated raindrops for rain/drizzle/
thunderstorm codes, and gently drifting snowflakes for snow codes.
Intensity (light/moderate/heavy) scales particle count and speed.
The overlay is pointer-events-none at z-[100] so it doesn't block
interaction.
When a quoted event fails to load, the 'this post could not be loaded'
indicator is now clickable, navigating to the event's page. Constructs
nevent1 for regular events and naddr1 for addressable events, including
relay hints and author pubkey when available from the parent event's tags.
Use the free Open-Meteo API to show real-time weather (temperature,
humidity, wind, conditions) on country and subdivision pages. Weather
is fetched based on capital city / major city coordinates and cached
for 15 minutes.
The footer links (About, Docs, Privacy, Edit with Shakespeare) were
showing in both the left sidebar and right sidebar on desktop. Remove
from LeftSidebar since it already appears in MobileDrawer for mobile
and in the right sidebars for desktop.
Closes#131
- Remove incubation_time and start_incubation from coreStateTags in
buildMigrationTags - these obsolete fields should not be carried
forward during migration
- Add DEPRECATED_BLOBBI_TAG_NAMES to the exclusion set in buildMigrationTags
when filtering unknown tags, preventing deprecated tags from being
preserved in migrated events
- Add DEPRECATED_BLOBBI_TAG_NAMES filtering to mergeTagsForRepublish so
deprecated tags are not carried forward when republishing existing events
The deprecated tags (incubation_time, start_incubation, incubation_progress,
egg_status, fees) are now properly excluded from:
1. New events (already handled by buildEggTags)
2. Migrated events (buildMigrationTags)
3. Republished events (mergeTagsForRepublish, mergeBlobbiStateTagsForRepublish)
Legacy parsing still reads these fields for backwards compatibility, but
they are never written to new events.
The isValidBlobbiEvent function only accepted 3 states (active, sleeping,
hibernating) but BlobbiState type includes 5 states. When state changed to
'incubating' or 'evolving', events failed validation and were filtered out
by useBlobbisCollection and useBlobbiCompanion hooks.
Added 'incubating' and 'evolving' to the valid states list.
Deprecated tags removed from creation:
- incubation_time: No longer created in buildEggTags or previewToEventTags
- start_incubation: No longer in managed tags
- egg_status: Removed from LEGACY_VISUAL_TAG_NAMES (was duplicated)
These tags are now in DEPRECATED_BLOBBI_TAG_NAMES and stripped on republish.
Visual trait consistency:
- buildEggTags now includes all visual traits (base_color, secondary_color,
eye_color, pattern, special_mark, size) derived from seed
- VISUAL_TRAIT_TAG_NAMES replaces LEGACY_VISUAL_TAG_NAMES
- Visual traits added to MANAGED_BLOBBI_STATE_TAG_NAMES
Stat safety:
- STAT_MIN = 1 (was 0) to prevent soft-lock
- STAT_MAX = 100
- clampStat now clamps to 1-100 range instead of 0-100
- Recovery is always possible with any healing item
Layout improvements:
- BlobbiPage container: max-w-2xl on mobile, max-w-3xl on desktop
- Reduced side whitespace on mobile (px-2)
- Better breathing room overall
BlobbiCompanion interface:
- incubationTime and startIncubation marked as @deprecated
- DEFAULT_INCUBATION_TIME marked as @deprecated
state_started_at remains the single source of truth for process timing.
- Apply accumulated decay from last_decay_at to now before state change
- Write decayed stat values into the incubation-start event
- Set last_decay_at = state_started_at = last_interaction for consistency
- Add incubation_progress, egg_status, fees to DEPRECATED_BLOBBI_TAG_NAMES
The incubation-start event now has consistent timestamps:
- created_at: NOW
- state_started_at: NOW
- last_interaction: NOW
- last_decay_at: NOW (was incorrectly preserving old value)
- Fix Color Moment URL: espy.social -> espy.you
- Improve shape-change task detection: only counts true post-start changes
- Remove duplicate Start Incubation button, integrate into evolve/hatch button
- Extract shared incrementInteractionTaskTags helper for code reuse
- Update floating controls to show incubation action for eggs not yet incubating
The evolve/hatch button now serves as the single entry point:
- Egg (not incubating): Opens incubation dialog
- Egg (incubating): Button hidden, hatch action in HatchTasksPanel
- Baby: Evolves to adult
Remove the Messages tab and add a Feed tab (using PlanetIcon) as the
leftmost item in the mobile bottom navigation. Feed highlights when
on /feed or /.
Allow users to upload their own .woff2/.woff/.ttf/.otf font files via
Blossom, which are immediately applied and stored with the theme. The
uploaded font URL is preserved when publishing themes to Nostr (via the
existing f tag in the theme event schema).
The inventory modal's use confirmation dialog was showing simple
multiplication (effect * quantity) instead of the actual clamped
values that would be applied.
Now it simulates the sequential application of effects, clamping
at each step, to show the true total effect that will be applied
when confirming. This matches the behavior of the action modal's
confirmation dialog.
- Add quantity selector to item usage modal (feed/play/clean/medicine)
- Users can now use multiple items at once
- Effects are applied sequentially with proper clamping at each step
- Shows estimated total effect preview
- Add 'Use' button to inventory modal
- Items can now be used directly from inventory
- Reuses same logic as normal item usage flow
- Opens confirmation dialog with quantity selector
- Add stage-based item blocking in inventory
- Eggs cannot use food or toys (shown disabled with reason)
- Shell Repair Kit only usable by eggs (blocked for baby/adult)
- Blocked items remain visible but cannot be used
- Shell Repair Kit visibility in medicine modal
- Only appears for eggs, hidden for other stages
- Make shop modal narrower (max-w-4xl to max-w-2xl)
- Add centralized item usability logic (canUseItemForStage)
- Single source of truth for item/stage restrictions
- Exported from actions module for reuse
The hover overlay was showing as a full rectangle instead of respecting
the Blobbi shape mask. This happened because the overlay was using the
sync getAvatarMaskUrl() which returns empty for Blobbi shapes (they now
render asynchronously as PNG).
Changed ProfileCard to:
- Use getAvatarMaskUrlAsync() for the overlay mask
- Load mask URL via useEffect with proper cleanup
- Apply the same mask to the hover overlay as the avatar itself
Now the hover/edit darkening effect respects the actual avatar shape,
only appearing inside the visible silhouette.
CSS mask-image with SVG data URLs doesn't work reliably for complex SVGs
with transforms in some browsers. The picker preview works because it renders
inline SVG directly, but the avatar mask-image was failing for shapes like
droppi, flammi, leafy, mushie, owli, rocky, and rosey.
Changes:
- Rewrite getBlobbiMaskUrl() to render SVG to canvas and export PNG
- Use Blob URL for SVG loading (more reliable than data URL)
- Add async mask generation with proper caching and deduplication
- Update Avatar component to load masks asynchronously via useEffect
- Add getAvatarMaskUrlAsync() for async mask URL retrieval
The picker preview continues to use inline SVG (which works fine),
while the avatar mask now uses rasterized PNG (which works everywhere).
The previous approach using <style> tags with CSS selectors inside SVG data URLs
didn't work reliably when the SVG was used as a CSS mask-image. Some browsers
don't process CSS inside SVG data URLs correctly.
This fix:
- Adds injectWhiteFillStroke() function to directly inject fill="white" and
stroke="white" attributes into each SVG shape element
- Properly handles elements with transform attributes (the root cause of
droppi, flammi, leafy, mushie, owli, rocky, rosey failing)
- Preserves fill="none" for stroke-only elements (like catti's tail)
- Works reliably across all browsers since it uses SVG attributes, not CSS
1. Remove stroke="white" from catti shape - let the styling apply colors
2. Fix Avatar component to properly update mask when shape changes:
- Compute maskUrl outside useMemo so it's always fresh
- Use maskUrl directly in dependencies instead of shape string
- This ensures the mask updates immediately when selecting a new shape
The previous implementation tried to render SVG to canvas synchronously,
but Image loading is asynchronous, causing getBlobbiMaskUrl() to return
empty string and avatars to fall back to squares.
CSS mask-image supports SVG data URLs directly, so we now skip the
canvas conversion entirely. This is simpler, more reliable, and works
synchronously.
- Remove renderSvgToMaskUrl() and drawImageToCanvas() functions
- Simplify getBlobbiMaskUrlAsync() to just wrap sync version
- Use fill/stroke attributes on <g> instead of global CSS to prevent color leakage
- Reduce grid columns from 5 to 4 for larger shape previews
- Reduce inner padding from inset-1 to inset-0.5 for bigger shapes
- Change BlobbiShape type from 'path: string' to 'svg: string'
- Store original SVG body markup preserving circles, ellipses, rects, paths, transforms, and strokes
- Update getBlobbiMaskUrl() to render SVG string via Image element instead of Path2D
- Add getBlobbiMaskUrlAsync() for guaranteed async loading
- Add getBlobbiShapeSvg() helper to get complete SVG markup with custom fill
- Update BlobbiShapePicker to render multi-element SVG with dangerouslySetInnerHTML
- Shapes now visually match original SVG files exactly (e.g., catti tail is stroke-based)
- Add tight viewBox computation for better shape visibility in picker
- Change grid layout to 5 columns for larger, more prominent shapes
- Remove shape name labels for cleaner picker interface
- Rename 'Blobbi' tab to 'Blobbids' in avatar picker dialog
- Update all adult Blobbi SVGs with refined designs
- Redesign shape paths with detailed silhouettes including limbs and accessories
- Add pot to Leafy, adjust Pandi arms, remove shadows from Rocky
Add the attribute to the file input in ComposeBox and update
the onChange handler to iterate over all selected files, uploading each
one via handleFileUpload, enabling users to select and attach multiple
files at once.
- Fix color moments rendering long text as emoji overlay; only render
single emoji (≤2 code points) as palette overlay
- Replace MapPin with ChestIcon on geocache name
- Add geohash pill badge to geocache type/size row, linking to /g/ route
- Truncate geohash display to 5 characters
- Add /g/:geohash route with GeotagPage backed by shared TagFeedPage
- DRY up HashtagPage and GeotagPage into shared TagFeedPage component
- Extend useInterests to support g tags for geohash following
- Add geotag feed tabs to home feed with MapPin icon
Break the dialog into 3 focused steps (Scope, Details, Confirm)
with animated progress indicators, dramatic destructive color
treatment, custom scope selection cards, and a centered final
confirmation with type-to-confirm input.
Implement kind 62 event publishing to allow users to request
permanent deletion of their data from relays. Includes global
(ALL_RELAYS) and targeted (specific relays) modes with a
multi-step confirmation dialog in Advanced Settings.