Reduce font complexity from two-role (title/body) to a single font
that applies globally to all text. Updates NIP.md f tag format from
["f", family, role, url] to ["f", family, url], removes ThemeFonts
wrapper in favor of a single ThemeFont on ThemeConfig.font, and
simplifies FontPicker to a single dropdown.
ThemeSelector was constructing a new ThemeConfig with only colors when
sharing, discarding the fonts and background from the customTheme.
Now passes the full customTheme (which already is a ThemeConfig).
- Add ThemeConfig wrapper type (colors + fonts + background) replacing bare CoreThemeColors
- Sync theme event parsing/building with NIP.md spec: colors in c tags (hex), fonts in f tags, background in bg tags (imeta-style), empty content field
- Legacy backward compat: parse old JSON-in-content format and bare CoreThemeColors in localStorage/encrypted settings
- Bundle 10 curated fonts via fontsource (Inter, DM Sans, Outfit, Montserrat, Lora, Merriweather, Playfair Display, JetBrains Mono, Comfortaa, Comic Neue) with lazy dynamic imports
- Create font loader (src/lib/fontLoader.ts) for @font-face injection from remote URLs and CSS override application for title/body roles
- Rewrite FontPicker as dual title/body picker using bundled fonts instead of Google Fonts CDN
- Remove Google Fonts integration (useGoogleFont.ts, GoogleFontLoader.tsx)
- Resolve bundled font family names to CDN URLs when publishing to Nostr
- Apply profile theme fonts when visiting other users' profiles
- Update all consumers: AppProvider, useTheme, usePublishTheme, useEncryptedSettings, ThemeSelector, ThemeBuilderPage, ProfilePage, EditProfileForm, InitialSyncGate, NostrSync
Loads any Google Font on demand, applies it site-wide via injected
stylesheet, and persists the selection in localStorage. Available
in Settings > Theme alongside the existing color theme selector.
When disableEmbeds is true, image-embed tokens now return null instead of
rendering the raw URL as a link. This fixes the triple-dot (more menu)
preview showing bare blossom/image URLs instead of clean post text.
- Images now render inline via NoteContent at the position of their URL
rather than collected into a gallery block below the text
- Clicking an inline image opens a full lightbox with navigation across
all images in the post; lightbox index is tracked by position so
duplicate URLs open at the correct index
- Removed separate ImageGallery/extractImages from NoteCard,
PostDetailPage, and ComposeBox to prevent double-rendering
- Added disableEmbeds to NoteMoreMenu clamped preview to avoid block
embeds inside a line-clamp-3 container
- Fixed hasPreviewableContent in ComposeBox to detect image-only posts
so the Preview tab appears correctly
- Removed mp3/ogg/wav/pdf from MEDIA_URL_REGEX suppression list; those
URLs now render as clickable links instead of being silently dropped
- Added avif to IMAGE_URL_REGEX; added cursor-pointer to InlineImage
Publish a new kind 11667 event with empty content and tags to clear
the active profile theme, replacing the previous kind 5 deletion
approach. The parser already returns null for empty content, so the
toggle state updates correctly.
Pass the event ID of the active profile theme to clearActiveTheme so
the kind 5 deletion includes both an 'a' tag and an 'e' tag. Updated
all call sites (ThemeSelector and EditProfileForm).
Merge upstream changes with the theme settings refactor. Adds a
'Display my theme to others' toggle that publishes a kind 11667
active profile theme event when enabled and issues a kind 5 deletion
when disabled. Split /settings/appearance into /settings/theme and
/settings/content. Move theme builder to /settings/theme/edit.
Add 'theme' to BUILTIN_SIDEBAR_ITEMS so it can be added to the left
sidebar via the More menu or drag-and-drop. Uses the Paintbrush icon
and navigates to /settings/theme. Active state detection distinguishes
it from the general Settings highlight.
The color pickers are now always visible below the theme grid,
reflecting the effective colors of whatever theme is active. Changing
a color automatically switches to a custom theme. Removed the
explicit Custom card and the customSelected state tracking.
Remove 'Create Theme' and 'Public Themes' buttons from the theme
selector. Add a 'Custom' option at the end of the presets grid that
opens an inline color editor (background, text, primary) with live
preview. The Custom option auto-selects on page load when the active
theme doesn't match any preset.
Replace the tabbed Appearance settings page with two separate pages:
- /settings/theme for theme selection
- /settings/content for feed and content preferences
Move the theme builder from /settings/theme to /settings/theme/edit to
avoid the route conflict. Update all navigation links across the codebase.
Add explicit `id` field to ExtraKindDef and remove the `__` prefix
convention for built-in items. Item IDs are now plain strings that don't
need to match URL paths. Route resolution goes through the definition's
`route` field instead of assuming id === route.