Move build-time ditto.json injection from a Vite define global to
import.meta.env.DITTO_CONFIG (a JSON string parsed and validated at
runtime via DittoConfigSchema). Remove the global type declaration
from vite-env.d.ts.
Drop ThemeSchemaCompat and its legacy "black"/"pink" migration code
from AppProvider and NostrSync — invalid theme values now simply fail
Zod validation.
Fix a latent bug where a partial feedSettings from ditto.json would
replace the full hardcoded defaults; defaultConfig now deep-merges
feedSettings.
- Combine Shop and Inventory into a single tabbed dialog (Shop tab
with category sub-tabs, Inventory tab with item list and use flow)
- Remove BlobbiInfoModal entirely
- Move dev tools (Dev Hatch/Evolve, State Editor, Emotion Tester) into
the bottom bar 'More' dropdown with yellow text, remove floating
dev tools panel
- Remove 'visibleToOthers' / 'visible_to_others' concept from the
entire codebase: types, interfaces, tag schemas, event construction,
parsing, UI badges, dev editor, and documentation
- Replace chevron up/down buttons with @dnd-kit SortableList/SortableItem
for proper drag-and-drop reorder in EmojiPackDialog
- Remove 'N emojis' badge from emoji pack display
- Make '+N' overflow indicator clickable to expand full emoji grid
- Stop click propagation on expand button to prevent feed navigation
- Resolve shortcode collisions across emoji packs by prefixing with pack
d-tag identifier when two packs define the same shortcode with different URLs
Replace the cluster of floating action buttons on the right side of the
Blobbi dashboard with a single 'More' dropdown in the bottom control bar.
The menu contains: Inventory, Take a Photo, Set as Companion, Evolve/Hatch,
Blobbi Info, and View Blobbi. The floating controls now only show the back
button (left) and dev tools (right, localhost only).
- Swap native HTML drag-and-drop reorder for chevron up/down buttons,
fixing scroll conflicts inside ScrollArea and drop zone interference
- Remove the colon decorations around shortcode inputs
- Show plain 'N emojis' count without parenthetical upload note
Files are held as local blob previews while editing. Nothing is
uploaded or signed until the user clicks the publish button, at which
point all pending files are uploaded in parallel and then the event
is published in a single batch.
Add a 3-dots menu to the Blobbi dashboard with a 'View Blobbi' link that
navigates to the naddr detail page. Register kind 31124 (Blobbi Pet State)
across all UI registration points so Blobbi events render properly in
feeds, detail pages, comment contexts, and embedded previews.
Introduce EmojiPackDialog for publishing and editing kind 30030 custom
emoji sets (NIP-30). The dialog supports multi-file and folder
drag-and-drop, automatically extracting shortcodes from filenames. The
d-tag identifier is locked after initial publish. Existing packs show
an Edit button on the feed card for the author. The /emojis page FAB
now opens the create dialog.
Give ProfileRightSidebar its own query using a kind whitelist
(20, 21, 22, 34236, 36787, 34139, 30054, 30055) instead of
relying on the parent's search-based media query. This ensures
the desktop sidebar only shows media-native events, excluding
kind 1 text notes and kind 1111 comments at the query level.
The Media tab continues to use the broader useProfileMedia hook
with search: 'media:true' and is unaffected.
setQueryData requires an exact query key match, but the unread
notifications query uses a 4-element key (prefix, pubkey, kindsKey,
authorsKey). The markAsRead callback was calling setQueryData with only
2 elements, silently missing the cache entry. Switch to setQueriesData
which uses prefix matching, correctly hitting the real cache entry.
UX change: the first-hatch experience is now a focused onboarding screen
instead of a modal interruption.
Layout during first-hatch tour:
- Egg visual (top, with tour animations)
- Stats (if any visible)
- FirstHatchTourCard inline below stats (mission + post CTA)
- No floating hero controls (camera, info, companion, incubation)
- No bottom action bar (blobbies, missions, actions, shop, inventory)
- No inline activity area (music, sing)
The page feels like a dedicated guided flow rather than a dashboard
with overlays. Normal dashboard controls return after tour completion.
Architecture: clean branch in BlobbiDashboard render --
isFirstHatchTourActive gates visibility of controls/bar/activities.
The inline card lives at the same level as other content sections.
The first egg is treated as already in the hatch onboarding path
without requiring the normal 'start incubation' entry point.
Tour integration:
- Call useFirstHatchTour + useFirstHatchTourActivation in BlobbiDashboard
- Auto-advance: idle -> egg_ready_hint (immediate) -> show_hatch_modal (3s)
- Poll for valid hatch post during show_hatch_modal/await_create_post
- On post detected, advance to egg_glowing_waiting_click
- Missions button opens tour modal instead of normal missions during tour
- Hide incubation button during tour (tour handles the flow)
- Badge shows tour-specific remaining count (1 post mission)
Post phrase update:
- New format: 'Posting to hatch {Name} #blobbi' (was: 'Hello Nostr! Posting to hatch #name #blobbi #ditto #nostr')
- Update isValidHatchPost to check for phrase anywhere in content
- Add buildHatchPhrase helper
- Simplify BlobbiPostModal validation and tag extraction
Egg visual layer:
- Add EggTourVisualState type ('idle' | 'ready_hint' | 'glowing_waiting_click')
- Thread tourVisualState prop: BlobbiStageVisual -> BlobbiEggVisual -> EggGraphic
- ready_hint: auto-wiggle every 2.5s using existing egg-tap-wiggle animation
- glowing_waiting_click: enlarged pulsing glow via new egg-tour-glow CSS animation
- Add reduced-motion support for new animation
FirstHatchTourModal component:
- Shows during show_hatch_modal/await_create_post steps
- Single mission: create a hatch post with the required phrase
- Continue button appears when post is detected
New src/blobbi/tour/ module with:
- tour-types.ts: Generic TourStepDef/TourState/TourActions types, plus
FirstHatchTourStepId enum and ordered FIRST_HATCH_TOUR_STEPS array
- useFirstHatchTour: Step-based state machine with localStorage
persistence, advance/goTo/complete/reset actions, and derived
booleans (isStep, isAnyStep, currentStepDef) for UI consumption
- useFirstHatchTourActivation: Precondition guard that auto-starts
the tour when: exactly 1 Blobbi, egg stage, no baby/adult, not
yet completed
- Barrel index.ts exporting all types, hooks, and constants
No visual/UI changes yet -- this is the orchestration foundation
that rendering layers will plug into.
Egg stats no longer decay, so the 'Keep Egg Healthy' dynamic task is
unnecessary and misleading. Remove it along with HATCH_STAT_THRESHOLD.
The baby/adult 'Peak Condition' evolve task is unchanged.
Also hide the 'Set as Companion' button entirely for eggs instead of
rendering it as disabled.
Kind-specific pages (articles, photos, videos, etc.) clamped the feed tab
to 'follows' for all users, but the follows query requires a logged-in
user. Logged-out users saw infinite skeleton loading with no way to switch
tabs. Now defaults to 'global' when no user is present.
Remove Details tab and Save header icon. Metadata (image, summary, slug,
tags) now sits inline between title and editor body like Medium. Save Draft
button moved to bottom of compose form. Header tabs renamed to New and
My Articles.
Replace external Inkwell link with a built-in article creation experience.
Uses Milkdown editor with tabbed UI (Write/Details/Drafts) matching the
letters compose pattern, FAB publish button, relay+local draft support,
and kind 30023/30024 publishing.
The envelope previously showed flap-like V-fold lines on both sides,
which doesn't match how real envelopes work. Now the default view
shows the back/mailing side with sender name top-left and recipient
name centered, then flipping reveals the front with the triangular
flap and wax seal, and clicking opens the flap to reveal the Nushu
ciphertext.
Move the hardcoded < 70 stat visibility checks from BlobbiPage.tsx into
the shared getVisibleStatsWithValues() utility in blobbi-decay.ts. This
ensures egg, baby, and adult stages all use the same STAT_VISIBILITY_THRESHOLD
constant, and any future UI consuming visibleStats gets the filtering for free.
Clicking any egg triggers a playful rock-and-hop animation (0.6s)
that wobbles side to side with a small upward jump, then settles.
Uses CSS animation with onAnimationEnd to auto-reset state.
Respects prefers-reduced-motion and doesn't interrupt cracking.