- Remove redundant localStorage saves on every form change
- Only save draft when autosave status is 'error' or 'offline'
- Reduces draft recovery banner noise for successful autosaves
- Navigation guard still prevents data loss when navigating away
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update ProjectForm to use new createAutoSaveStore with Svelte 5 runes
- Fix $derived syntax in AutoSaveStatus (use $derived.by for multi-statement)
- Add hasLoaded flag to prevent infinite loop on autosave completion
- Move draft recovery from inline header to prominent banner below header
- Style draft banner with blue info colors and slide-down animation
- Fix draft persistence by clearing localStorage on restore/dismiss
- Call beforeNavigate at top level for proper Svelte 5 lifecycle
- Add keyboard shortcut (Cmd/Ctrl+S) and navigation guard effects
- Update AutoSaveStatus to support both old stores and new reactive props
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduces createAutoSaveStore() using $state() for automatic reactivity.
New store provides cleaner API while maintaining backward compatibility.
Changes:
- New: src/lib/admin/autoSave.svelte.ts with createAutoSaveStore()
- Uses $state() for status and lastError (reactive getters)
- Export AutoSaveStore and AutoSaveStoreOptions types
- Add JSDoc with usage examples
- Update autoSaveLifecycle.ts to accept both old and new types
- Export AutoSaveController type from old file for compatibility
Old createAutoSaveController() remains unchanged for gradual migration.
Type checking passes with no new errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhances autosave controller with missing features:
- prime(payload): Sets initial hash baseline to prevent autosaves on page load
- idleResetMs option: Auto-transitions from 'saved' → 'idle' status (default 2s)
- onSaved callback: Now receives { prime } helper for re-priming after server response
- Cleanup: destroy() now properly clears idle reset timer
All existing tests pass. Backward compatible - forms not using new features yet.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Introduces createListFilters() with type-safe, reactive filtering and sorting
for admin list pages. Eliminates ~120 lines of duplicate code across projects
and posts pages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add video player with controls in MediaDetailsModal
- Display video metadata (duration, codecs, bitrate) in metadata panel
- Show video thumbnails with play icon overlay in MediaGrid
- Support video preview in upload components
- Replace emoji icons with SVG play icon
- Maintain natural video aspect ratio in all views
- Add proper styling for video thumbnails and placeholders
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add video MIME types support (WebM, MP4, OGG, MOV, AVI)
- Increase upload size limit to 100MB for videos
- Add ffmpeg integration for local video processing
- Generate video thumbnails at 50% duration
- Extract video metadata (duration, codecs, bitrate)
- Add database fields for video metadata
- Support video uploads in both local and Cloudinary storage
- Maintain aspect ratio for video thumbnails (1920px max width)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix renderEdraContent to accept albumSlug option parameter
- Fix album listing links from /photos/{slug} to /albums/{slug}
- Remove album header section for cleaner photo story presentation
- Remove broken photo page conditional that was preventing render
- Pass album slug to content renderer for proper photo linking
Creates more immersive experience where content speaks for itself.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add URL field to Apple Music data type
- Include Apple Music URL in album transformation
- Prioritize Apple Music links over Last.fm in Album component
- Falls back to Last.fm URL when Apple Music data unavailable
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create CacheManager class to unify all Redis cache operations
- Define cache types with prefixes and default TTLs
- Provide type-safe cache operations
- Add bulk clear operations for related caches
- Include cache statistics and monitoring capabilities
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create DebugPanel component with Now Playing, Albums, and Cache tabs
- Show real-time connection status and update intervals
- Display detailed Apple Music data for each album
- Add inline cache clearing for individual albums
- Implement Apple Music search modal for testing queries
- Add admin endpoints for cache management and API testing
- Only visible in development mode
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add fallback to search for songs when album search fails
- Handle artist name variations (with/without spaces in Japanese names)
- Create synthetic album entries for singles not found as albums
- Add search metadata to track failed searches and debug info
- Fix Hachikō preview detection by normalizing artist names
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Adjust update frequency based on remaining track time
- Poll every 5s when <20s remaining, 10s for 20-60s, 15s for >60s
- Add heartbeat timestamps to track update timing
- Implement time-based fallback for tracks without Apple Music data
- Assume tracks scrobbled within 5 minutes are still playing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Merge albumStream and nowPlayingStream into unified musicStream store
- Simplify confidence scoring to binary detection (playing/not playing)
- Create single source of truth for music state across components
- Fix synchronization issues between header and album indicators
- Make Album spring animation more subtle (stiffness: 150, damping: 25)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Always fetch fresh data from Last.fm for now playing detection
- Add confidence-based detection with progress tracking
- Implement dynamic polling intervals (10s when playing, 30s idle)
- Add marquee animation for now playing text in header
- Fix release date formatting to show only year
- Add gradient fade effects to marquee edges
- Enhanced logging for debugging detection issues
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Show currently playing track info when hovering over avatar
- Display album artwork, artist name, and track/album name
- Add music note icons with pulse animation
- Maintain exact same container size as navigation
- Only shows when music is actively playing (avatar has headphones)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Japanese character detection to prioritize JP storefront
- Improve album/artist matching logic with helper functions
- Support flexible matching for albums with extra text (e.g., "- Single")
- Handle comma-separated artists by matching primary artist
- Clean up code by removing duplicate logic and verbose logging
- Fix issue where Japanese albums weren't found due to strict matching
This ensures albums like "ランデヴー" properly fetch artwork from Apple Music
even when Last.fm has no images available.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhance albumEnricher with better error handling and type safety
- Refactor lastfmStreamManager for cleaner event management
- Update lastfmTransformers with improved data validation
- Add better type guards in mediaHelpers
- Improve nowPlayingDetector logic and state management
- Enhance SSE error handling in Last.fm stream endpoint
Key improvements:
- Better error boundaries and fallback values
- More robust type checking and validation
- Cleaner async/await patterns
- Improved logging for debugging
- Consistent error response formats
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Migrate all Edra components to Svelte 5 with runes syntax
- Implement unified ContentInsertionPane for consistent content insertion
- Standardize placeholder components with improved layouts
- Enhance bubble menu with better color picker and text styling
- Improve drag handle interactions and visual feedback
- Update slash command system for better extensibility
Key improvements:
- ContentInsertionPane: New unified interface for all content types
- Placeholder components: Consistent sizing and spacing
- GeolocationPlaceholder: Simplified map integration
- UrlEmbedPlaceholder: Better preview handling
- ComposerMediaHandler: Converted to Svelte 5 class syntax
- BubbleMenu components: Enhanced UI/UX with modern patterns
All components now use:
- Interface Props pattern for better type safety
- $state and $derived for reactive state
- Modern event handling syntax
- Consistent styling with CSS variables
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add BasePane and Pane components for consistent panel UI
- Create pane-manager store for centralized pane state management
- Support for different pane positions and animations
- Establish foundation for unified pane behavior across the app
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create ContentInsertionPane component with segmented controls
- Update image placeholder to single-line format with icon + text
- Update gallery placeholder to use unified pane
- Support upload, embed link, and gallery selection for each type
- Add location search placeholder for future geocoding integration
- Add placeholder node styles to editor.css matching other media nodes
- Remove incorrect margins from individual placeholder components
- Placeholders now properly aligned with 2.25rem horizontal spacing
- Consistent with h1, h2, p text elements and YouTube embeds
- Fix slash command keyboard navigation by uncommenting handler
- Update all media placeholders to respect content block margins (2.25rem)
- Refactor placeholder styles to use SCSS variables consistently
- Fix Audio, Gallery, IFrame, Video, Location, and URL embed placeholders
- Fix Image placeholder width to match other placeholders
- Ensure responsive margins on mobile (2rem)
- Replace old slash command list styles with new design
- Use consistent SCSS variables from design system
- Match dropdown styling patterns used elsewhere
- Improve visual hierarchy with better typography
- Add smooth transitions and hover states
- Clean up old CSS styles
- Add left/right margins of 2.25rem to match text block padding
- Ensure YouTube videos, link cards, and other embeds align with text
- Add responsive margins (2rem) for mobile viewports
- Fixes issue where embeds were too wide compared to text content
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add 1rem margin-bottom to all embed types (url, iframe, video, image, gallery, audio, geolocation)
- Ensure YouTube embeds and URL cards have consistent spacing
- Prevent double margins when embeds are adjacent
- Matches the margin-bottom used for text blocks (paragraphs)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Always initialize editor with content to create paragraph node
- Remove logic that prevented setting empty paragraph content
- Remove unused initialized variable
- This ensures the placeholder is visible when editor first loads
The issue was that the editor needs at least one paragraph node
for the placeholder to display, but the previous logic prevented
this from happening on initial load.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>