This document provides a complete implementation plan for adding a Reflex-based web UI to PlexMix. Each phase is broken down into actionable TODO items that can be followed to coding completion.
+-------------------------------------------------------+
| Reflex Web UI (Browser) |
| Dashboard | Generator | Library | Tagging | History |
+-------------------------------------------------------+
^ v
Reflex State Management
(Hybrid: AppState + Page States)
^ v
+-------------------------------------------------------+
| Reflex Background Tasks (@rx.background) |
| Async generators with progress updates via yield |
+-------------------------------------------------------+
^ v
+-------------------------------------------------------+
| Existing PlexMix Modules (Shared) |
| PlexClient | SQLiteManager | AI Providers | etc. |
+-------------------------------------------------------+
^ v
+-------------------------------------------------------+
| Data Layer (Shared) |
| SQLite DB | FAISS Index | Keyring Config |
+-------------------------------------------------------+
- No Breaking Changes: All modifications to existing code are backward-compatible
- Code Reuse: Leverage all existing PlexMix modules directly
- Shared Config: CLI and UI use the same configuration system
- Progressive Enhancement: UI is an optional add-on, CLI remains fully functional
- Background Tasks: Use Reflex's native @rx.background decorator for long operations
- Hybrid State Management: Shared AppState for global data, page-specific states for local concerns
| Decision | Choice | Rationale |
|---|---|---|
| State Management | Hybrid (AppState + Page States) | Share common data, isolate page concerns |
| Background Tasks | Reflex @rx.background with async generators | Native support, clean API, real-time updates |
| Database Access | Read-direct, Write-queue pattern | Safe for SQLite's threading model |
| Component Library | Reflex + Chakra UI | Professional look, built-in support |
| Performance | Pagination + debounced search + SQL filtering | Handles 10K+ tracks smoothly |
Set up Reflex infrastructure, basic routing, and shared components.
- Add Reflex dependency to
pyproject.tomlunder[tool.poetry.dependencies] - Create optional extras group in
pyproject.tomlfor UI dependencies - Run poetry lock and install with UI extras
- Create
src/plexmix/ui/directory - Create
src/plexmix/ui/pages/directory - Create
src/plexmix/ui/states/directory - Create
src/plexmix/ui/components/directory - Create
src/plexmix/ui/utils/directory - Create
tests/ui/directory for UI tests - Create
assets/directory in project root for static assets - Create
__init__.pyfiles in all new Python directories
- Create
src/plexmix/ui/app.pyas main Reflex entry point - Define basic Reflex app instance with theme configuration
- Create simple index page component with welcome message
- Create placeholder dashboard page component
- Add routes for both pages to the app
- Test app runs with
reflex runcommand
- Add
uicommand tosrc/plexmix/cli/main.py - Command should accept host, port, and reload options
- Import and run Reflex app when command is invoked
- Add graceful error handling if Reflex is not installed
- Provide helpful message directing users to install UI extras
- Test command with
plexmix ui
- Create
src/plexmix/ui/components/navbar.py - Define navbar_link helper function for menu items
- Create navbar component with sidebar layout
- Include links for all 6 main pages (Dashboard, Generate, Library, Tagging, History, Settings)
- Add PlexMix logo/heading to navbar
- Style navbar with fixed position, background color, spacing
- Create layout wrapper function that includes navbar and content area
- Set content area margin to account for fixed navbar width
- Create
src/plexmix/ui/components/progress_modal.py - Define modal component that accepts progress value and message
- Include progress bar, status message, and cancel button
- Make modal reusable for any background task
- Create
src/plexmix/ui/components/toast.py - Define toast notification system for success/error/warning messages
- Support different color schemes based on message type
- Include auto-dismiss functionality
- Verify
plexmix uilaunches dev server - Confirm navigation between index and dashboard pages works
- Check navbar appears on all pages
- Validate all navigation links are present and styled correctly
- Test dev server hot-reload functionality
Deliverable: Basic running Reflex app with navigation
Implement configuration pages and overview dashboard.
- Create
src/plexmix/ui/states/app_state.py - Define AppState class inheriting from rx.State
- Add state variables for config status (plex_configured, ai_provider_configured, embedding_provider_configured)
- Add state variables for library stats (total_tracks, embedded_tracks, last_sync)
- Add state variables for background task tracking (current_task, task_progress)
- Implement
on_loadmethod to check configuration status - Create helper method to check if API keys exist for providers
- Create helper method to load library stats from database
- Handle case where database doesn't exist yet (fresh install)
- Import existing config and credentials modules
- Create
src/plexmix/ui/states/dashboard_state.py - Define DashboardState inheriting from AppState
- Add state variable for recent playlists list
- Implement method to load recent playlists from database
- Add method to refresh library stats on demand
- Handle errors gracefully with try-except blocks
- Create
src/plexmix/ui/pages/dashboard.py - Import DashboardState and layout component
- Create status_card component function for config status display
- Show green/red badge based on configuration status
- Include "Configure" link when not configured
- Create stats_card component function for library statistics
- Build main dashboard layout with heading
- Add configuration status section with cards for Plex, AI, Embeddings
- Add library stats section with total tracks and embedded count
- Add quick actions section with buttons for Generate and Sync
- Disable buttons when required config is missing
- Wire up button clicks to navigate to appropriate pages
- Use consistent spacing and alignment
- Update app.py to use dashboard_page with on_load callback
- Create
src/plexmix/ui/states/settings_state.py - Define SettingsState inheriting from AppState
- Add state variables for all Plex config fields (url, token, library)
- Add state variables for AI provider config (provider, api_key, model, temperature)
- Add state variables for embedding provider config (provider, api_key, model)
- Add state variables for advanced settings (db_path, batch_sizes, log_level)
- Add state variables for UI feedback (testing_connection, connection_status, active_tab)
- Implement method to load current settings from config module
- Implement method to save settings back to config module
- Create async test_plex_connection method with background decorator
- Attempt to connect to Plex server and return status
- Update connection_status state variable with results
- Create async test_ai_provider method
- Make test API call and return success/failure
- Create async test_embedding_provider method
- Generate test embedding and return success/failure
- Implement save_all_settings method to persist changes
- Call appropriate credential storage functions
- Update settings YAML file
- Show success toast on save
- Create
src/plexmix/ui/pages/settings.py - Import SettingsState and layout component
- Create tabbed interface using Reflex tabs component
- Create first tab for Plex configuration
- Add text input for Plex server URL with label and placeholder
- Add text input for Plex username
- Add password input for Plex token
- Add help text or link explaining how to get Plex token
- Add select dropdown for music library (populated after connection)
- Add "Test Connection" button
- Wire button to call test_plex_connection method
- Show loading spinner while testing
- Display connection status with color-coded badge
- Add "Save" button to persist Plex settings
- Create second tab for AI provider configuration
- Add select dropdown for provider (Gemini, OpenAI, Claude, Cohere)
- Add password input for API key
- Add select dropdown for model (options based on selected provider)
- Dynamically populate model options when provider changes
- Add slider for temperature (0.0 to 1.0)
- Display current temperature value
- Add "Test Provider" button
- Wire button to test_ai_provider method
- Show loading state during test
- Display test result with success/error message
- Add optional cost estimate calculator UI
- Add "Save" button for AI settings
- Create third tab for embedding provider configuration
- Add select dropdown for provider (Gemini, OpenAI, Cohere, Local)
- Add password input for API key (hidden if Local selected)
- Add select dropdown for model
- Display embedding dimension as read-only text (based on model)
- Add "Test Embeddings" button
- Wire button to test_embedding_provider method
- Show loading state during test
- Display test result
- Add "Save" button
- Create fourth tab for advanced settings
- Add read-only text display for database path
- Add browse button to change database location (optional)
- Add read-only text display for FAISS index path
- Add number input for sync batch size
- Add number input for embedding batch size
- Add select dropdown for logging level (DEBUG, INFO, WARNING, ERROR)
- Add "Save" button
- Navigate to dashboard and verify config status cards display correctly
- Navigate to settings and verify all tabs are present
- Test Plex connection with valid credentials
- Test Plex connection with invalid credentials
- Verify library dropdown populates after successful connection
- Test AI provider with valid API key
- Verify model dropdown changes when provider changes
- Test temperature slider updates value display
- Save settings and verify they persist after page reload
- Verify settings are accessible from CLI (shared config)
- Check that dashboard updates after settings are saved
Deliverable: Fully functional settings page and dashboard with live config status
Browse library, trigger syncs, manage tracks with real-time progress.
- Open
src/plexmix/database/sqlite_manager.py - Add
get_tracksmethod with pagination parameters (limit, offset) - Add optional search parameter to filter by title/artist/album
- Add optional genre filter parameter
- Add optional year range filter parameters
- Use SQL WHERE clauses for filtering
- Add
count_tracksmethod that accepts same filter parameters - Return total count matching filters
- Add
count_tracks_with_embeddingsmethod - Add
get_last_sync_timemethod to retrieve last sync timestamp - Ensure all queries use proper parameterization to prevent SQL injection
- Add indexes on commonly filtered columns (genre, year) for performance
- Open
src/plexmix/plex/sync.py - Add optional
progress_callbackparameter to main sync function - Add optional
cancel_eventparameter for cancellation support - Emit progress updates at regular intervals (e.g., every 10 tracks)
- Pass progress value (0.0 to 1.0) and descriptive message to callback
- Check cancel_event periodically and stop if set
- Make parameters default to None for backward compatibility
- Test that sync still works without callbacks (CLI compatibility)
- Create
src/plexmix/ui/states/library_state.py - Define LibraryState inheriting from AppState
- Add state variables for tracks list and total count
- Add state variables for pagination (current_page, page_size)
- Add state variables for filters (search_query, genre_filter, year_min, year_max)
- Add state variables for sync status (sync_in_progress, sync_progress, sync_message, sync_error)
- Add state variable for selected tracks (for bulk operations)
- Implement
load_tracksmethod to query database with current filters and pagination - Calculate offset from current_page and page_size
- Update tracks and total_tracks state variables
- Implement
next_pageandprev_pagemethods to update current_page - Implement
set_search_querymethod with debouncing - Use asyncio.create_task to delay execution
- Cancel pending search if new query arrives
- Implement background
start_syncmethod with @rx.background decorator - Use async with self to acquire state lock before updates
- Create async generator that yields progress updates
- Import sync function from plex module
- Pass progress callback that yields to frontend
- Handle errors and update sync_error state
- Implement
cancel_syncmethod to set cancellation flag - Implement
generate_embeddingsmethod for selected tracks - Similar background task pattern as sync
- Create
src/plexmix/ui/components/track_table.py - Define track_table function that accepts tracks list
- Use Reflex table component with proper headers
- Add columns: Checkbox, Title, Artist, Album, Genre, Year, Tags, Embedding Status
- Make embedding status a badge (green if exists, gray if not)
- Add row actions: View details, Edit tags buttons
- Make columns sortable
- Add hover effects for better UX
- Support bulk selection with checkboxes
- Add "Select All" checkbox in header
- Make table responsive
- Create
src/plexmix/ui/pages/library.py - Import LibraryState and layout component
- Add page heading
- Create action bar with horizontal stack layout
- Add "Sync Library" button
- Wire to start_sync method
- Show loading spinner when sync in progress
- Disable button during sync
- Add search input box
- Wire to set_search_query method
- Add debounce so search triggers after typing stops
- Add genre filter dropdown
- Add year range inputs (min and max)
- Add "Generate Embeddings" button for selected tracks
- Disable when no tracks selected
- Display sync progress modal when sync is running
- Show progress bar with current percentage
- Display status message (e.g., "Fetching track 450/1523")
- Include cancel button that calls cancel_sync
- Auto-close modal when sync completes
- Import and use track_table component
- Pass tracks from state
- Add pagination controls below table
- Previous button (disabled on page 1)
- Page number display
- Next button (disabled on last page)
- Wire buttons to next_page and prev_page methods
- Add on_load callback to load initial tracks
- Navigate to library page
- Verify tracks load and display in table
- Test pagination controls work correctly
- Search for tracks and verify results filter correctly
- Apply genre filter and verify filtering
- Apply year range filter
- Click "Sync Library" and verify sync starts
- Check progress modal appears with progress bar
- Verify progress updates in real-time
- Test cancel button stops sync
- Wait for sync to complete and verify modal closes
- Verify track count updates after sync
- Select tracks and test "Generate Embeddings" button
- Test with large library (1000+ tracks) for performance
- Verify debounced search doesn't trigger on every keystroke
Deliverable: Browsable, searchable library with working sync and progress tracking
Core feature - AI-powered mood-based playlist generation.
- Open
src/plexmix/playlist/generator.py - Add optional
progress_callbackparameter to generation method - Emit progress during candidate track selection phase
- Emit progress during AI generation phase
- Make parameter default to None for backward compatibility
- Test generator still works without callback
- Open
src/plexmix/database/sqlite_manager.py - Create
playliststable schema if not exists - Columns: id, name, mood_query, track_ids (JSON), created_at, updated_at
- Add
save_playlistmethod to insert new playlist - Add
get_playlistsmethod to retrieve all playlists - Add
get_playlist_by_idmethod - Add
delete_playlistmethod - Add
update_playlistmethod - Ensure track_ids are properly serialized/deserialized as JSON
- Create
src/plexmix/ui/states/generator_state.py - Define GeneratorState inheriting from AppState
- Add state variables for mood query input
- Add state variables for advanced options (max_tracks, genre_filters, year_range)
- Add state variable for include/exclude artists lists
- Add state variables for generation status (generating, progress, progress_message)
- Add state variable for generated playlist (list of track dicts)
- Add state variable for playlist metadata (total tracks, duration)
- Add state variable for playlist name (for saving)
- Add state variable for mood query examples list
- Implement background
generate_playlistmethod with @rx.background decorator - Use async with self for state updates
- Build filter criteria from advanced options
- Call playlist generator with progress callback
- Yield progress updates to frontend
- Store generated tracks in state
- Calculate total duration
- Handle errors gracefully
- Implement
regeneratemethod to generate again with same/modified query - Implement
save_to_plexmethod - Use PlexClient to create playlist on Plex server
- Show success/error toast
- Implement
save_locallymethod - Save playlist to database with name
- Show success toast
- Implement
export_m3umethod - Generate M3U file content
- Trigger download in browser
- Implement
remove_trackmethod to remove track from generated list - Implement
reorder_tracksmethod for drag-and-drop - Implement
use_examplemethod to populate query from example
- Create
src/plexmix/ui/pages/generator.py - Import GeneratorState and layout component
- Create two-column layout (40% input, 60% results)
- In left column, add large text area for mood query
- Add placeholder text like "Describe your mood or vibe..."
- Wire to mood_query state variable
- Create examples carousel or list
- Display 4-5 example queries ("Chill rainy day vibes", "Energetic workout", etc.)
- Make examples clickable to populate query
- Create collapsible advanced options section
- Add slider for max tracks (10-100 range)
- Add multi-select for genre filters
- Add year range inputs (min and max)
- Add text inputs for include/exclude artists
- Add large "Generate Playlist" button
- Wire to generate_playlist method
- Disable during generation
- Show loading spinner when generating
- In right column, add conditional display based on generation state
- Show loading animation when generating is true
- Include AI thinking message
- Show progress bar with current percentage
- Display progress message
- When playlist is generated, display results table
- Columns: Track number, Title, Artist, Album, Duration
- Add remove button for each track
- Implement drag-and-drop reordering if possible with Reflex
- Display playlist metadata above table
- Show total tracks count
- Show total duration (calculate from track lengths)
- Show mood query used
- Create actions section below table
- Add "Regenerate" button
- Add "Save to Plex" button with loading state
- Show input for playlist name when saving
- Add "Save Locally" button
- Add "Export M3U" button
- Wire all buttons to respective state methods
- Handle empty results case with helpful message
- Navigate to generator page
- Click example query and verify it populates input
- Expand advanced options and set filters
- Enter mood query and click generate
- Verify progress modal appears
- Check progress updates in real-time
- Wait for generation to complete
- Verify playlist displays with correct tracks
- Test remove track button
- Test reordering tracks (if implemented)
- Click "Save to Plex" and verify playlist appears in Plex
- Enter playlist name and save locally
- Verify playlist saved to database
- Click "Export M3U" and verify file downloads
- Test regenerate with modified query
- Test with different AI providers
- Test with empty library (should show helpful error)
- Test with filters that match no tracks
Deliverable: Complete AI-powered playlist generation workflow
Batch AI tag generation and tag management.
- Open
src/plexmix/ai/tag_generator.py - Add optional
progress_callbackparameter to batch tagging method - Emit progress after each batch of tracks tagged
- Include batch number, total batches, and tracks tagged count
- Add optional
cancel_eventparameter for cancellation - Check cancel event between batches
- Make parameters default to None for backward compatibility
- Open
src/plexmix/database/sqlite_manager.py - Add method to count untagged tracks
- Add method to get tracks by filter criteria (for tag selection)
- Add method to update track tags (tags, environments, instruments)
- Add method to get recently tagged tracks (last N tracks)
- Ensure tag fields can store comma-separated or JSON arrays
- Create
src/plexmix/ui/states/tagging_state.py - Define TaggingState inheriting from AppState
- Add state variables for filter criteria (genre, year_range, artist, has_no_tags)
- Add state variable for preview count (tracks matching filters)
- Add state variables for tagging status (in_progress, progress, current_batch, total_batches)
- Add state variable for tags generated count
- Add state variable for recently tagged tracks list
- Add state variable for estimated time remaining
- Implement
preview_selectionmethod to count matching tracks - Query database with filter criteria
- Update preview_count state
- Implement background
start_taggingmethod with @rx.background decorator - Use async with self for state updates
- Query tracks matching filters
- Call tag generator with progress callback
- Yield progress updates to frontend
- Update tags_generated counter
- Refresh recently tagged tracks when done
- Handle errors and show error state
- Implement
cancel_taggingmethod to set cancellation flag - Implement
update_tagmethod for inline editing - Update database with new tag value
- Refresh recently tagged tracks
- Implement
tag_all_untaggedpreset method - Set filters to match untagged tracks only
- Call start_tagging
- Create
src/plexmix/ui/pages/tagging.py - Import TaggingState and layout component
- Add page heading
- Create selection panel at top
- Add "Tag All Untagged Tracks" button as quick action
- Wire to tag_all_untagged method
- Add divider with "OR" text
- Create custom filter builder section
- Add genre multi-select dropdown
- Add year range inputs (min and max)
- Add artist search/filter input
- Add checkbox for "Has no tags"
- Add "Preview Selection" button
- Wire to preview_selection method
- Display preview count prominently
- Show count like "X tracks match filters"
- Add large "Start Tagging" button
- Disable if preview count is 0
- Wire to start_tagging method
- Create progress section (visible when tagging is in progress)
- Show overall progress bar
- Display current batch info (e.g., "Batch 3/10")
- Show number of tracks being processed in batch
- Display tags generated count
- Show estimated time remaining if available
- Add cancel button
- Wire to cancel_tagging method
- Hide progress section when not tagging
- Create section below progress for recently tagged tracks
- Add heading "Recently Tagged Tracks"
- Create table with columns: Title, Artist, Tags, Environments, Instruments
- Display last 100 tagged tracks
- Add edit button for each row
- Implement inline editing mode
- Show input fields when edit is clicked
- Add save/cancel buttons for edits
- Wire save to update_tag method
- Add pagination if needed for large result sets
- Show empty state when no recently tagged tracks
- Navigate to tagging page
- Click "Tag All Untagged Tracks"
- Verify preview count shows correct number
- Click "Start Tagging" and verify progress appears
- Check progress bar updates in real-time
- Verify batch info displays correctly
- Wait for tagging to complete
- Check recently tagged tracks table populates
- Test custom filter builder
- Set various filter combinations
- Preview selection and verify count changes
- Start tagging with custom filters
- Test cancel button stops tagging
- Test inline tag editing
- Edit a tag and save
- Verify tag updates in database
- Test with different AI providers
- Test with large batch (100+ tracks)
Deliverable: AI tagging interface with batch processing and editing
View and manage saved playlists.
- Create
src/plexmix/ui/states/history_state.py - Define HistoryState inheriting from AppState
- Add state variable for playlists list
- Add state variable for selected playlist details
- Add state variable for detail modal visibility
- Add state variable for sorting/filtering options
- Implement
load_playlistsmethod - Query database for all saved playlists
- Sort by created date (newest first)
- Update playlists state variable
- Implement
select_playlistmethod to view details - Load full playlist details including tracks
- Update selected_playlist state
- Show detail modal
- Implement
delete_playlistmethod - Delete from database
- Show confirmation dialog before deletion
- Reload playlists after deletion
- Show success toast
- Implement
export_to_plexmethod - Similar to generator's save_to_plex
- Use playlist data to create on Plex server
- Implement
export_to_m3umethod - Generate M3U file from playlist
- Trigger download
- Implement
close_detail_modalmethod - Add on_load callback to load playlists
- Create
src/plexmix/ui/pages/history.py - Import HistoryState and layout component
- Add page heading
- Create grid layout for playlist cards
- Use responsive grid (2-4 columns based on screen width)
- For each playlist, create card component
- Display playlist name as heading
- Show mood query as subtitle
- Display track count and total duration
- Show created date
- Create thumbnail from first 4 album arts in 2x2 grid
- Or use placeholder if album art not available
- Add hover effect to show action buttons
- Include "View Details" button
- Include "Export to Plex" button
- Include "Export M3U" button
- Include "Delete" button (with warning icon)
- Wire all buttons to respective state methods
- Show empty state if no playlists saved
- Add helpful message and link to generator
- Create modal component for playlist details
- Bind visibility to detail modal state variable
- Display playlist name as modal header
- Show mood query prominently
- Display metadata (track count, duration, created date)
- Create table for full track listing
- Columns: Track number, Title, Artist, Album, Duration
- Make table scrollable if many tracks
- Add actions section in modal footer
- "Export to Plex" button
- "Export M3U" button
- "Delete Playlist" button
- "Close" button
- Wire buttons to state methods
- Show confirmation dialog before deletion
- Navigate to history page
- Verify empty state shows when no playlists
- Generate and save a playlist from generator page
- Return to history and verify playlist appears
- Check card shows correct information
- Hover over card and verify action buttons appear
- Click "View Details" and verify modal opens
- Check all playlist information displays correctly
- Test "Export to Plex" from both card and modal
- Verify playlist appears in Plex
- Test "Export M3U" and verify download
- Test delete with confirmation dialog
- Verify playlist removed from grid after deletion
- Create multiple playlists and verify grid layout
- Test with playlists of varying lengths (5 tracks, 50 tracks, etc.)
Deliverable: Playlist history viewing and management interface
Refinement, optimization, comprehensive testing, and documentation.
- Review all pages for loading states
- Add skeleton screens while data loads
- Use Reflex skeleton components for tables and cards
- Add loading spinners for buttons during async operations
- Ensure all background tasks show progress or loading indicators
- Add transitions/animations for smooth UX
- Test all loading states appear correctly
- Verify loading states dismiss when operation completes
- Review all async operations for error handling
- Wrap operations in try-except blocks
- Show user-friendly error messages via toast
- Log detailed errors to console for debugging
- Add error boundaries for page-level errors
- Create fallback error page with helpful message
- Test with invalid inputs (bad URLs, wrong API keys, etc.)
- Test network failures (disconnect during operation)
- Verify all errors show helpful messages, not stack traces
- Add retry buttons where appropriate
- Add client-side validation for all form inputs
- Validate URLs match expected format
- Validate API keys meet length requirements
- Validate numeric inputs are in valid ranges
- Show inline error messages for invalid inputs
- Prevent form submission when validation fails
- Add real-time validation as user types (debounced)
- Use color coding (red borders) for invalid fields
- Show green checkmarks for valid fields
- Test all validation scenarios
- Implement keyboard shortcuts for common actions
- Add Ctrl/Cmd+K for global search
- Add Ctrl/Cmd+N for new playlist
- Add Ctrl/Cmd+S to save settings
- Add Esc to close modals
- Add keyboard navigation for lists and tables
- Display keyboard shortcuts in help section
- Test shortcuts work on different operating systems
- Profile page load times
- Optimize database queries with proper indexes
- Implement query result caching where appropriate
- Optimize component re-renders
- Use Reflex's memoization for expensive computations
- Implement virtual scrolling for very large lists (if needed)
- Test with large library (10,000+ tracks)
- Measure search response time
- Optimize image loading for playlist cards
- Use lazy loading for images
- Minify assets for production
- Test performance metrics meet success criteria
- Test UI on different screen sizes
- Desktop (1920x1080, 1366x768)
- Tablets (1024x768, 768x1024)
- Verify navbar collapses appropriately on smaller screens
- Check tables display properly or switch to card layout
- Ensure buttons and controls are touch-friendly
- Test modals are appropriately sized on all screens
- Fix any layout issues discovered
- Add mobile-specific optimizations if needed
- Create
tests/ui/test_states.py - Write unit tests for AppState methods
- Mock database and config calls
- Test state initialization
- Test configuration status checking
- Write tests for DashboardState
- Write tests for SettingsState
- Test connection testing methods
- Test save settings functionality
- Write tests for LibraryState
- Test pagination logic
- Test filter application
- Write tests for GeneratorState
- Test playlist generation logic
- Write tests for TaggingState
- Test filter preview and tagging
- Write tests for HistoryState
- Test playlist CRUD operations
- Ensure all tests pass
- Aim for >80% code coverage
- Create integration test scenarios
- Test complete user workflow: Setup → Sync → Generate → Save
- Test CLI and UI config compatibility
- Create config via CLI, verify visible in UI
- Create config via UI, verify CLI can use it
- Test with real Plex server
- Test with real AI providers (all 4: Gemini, OpenAI, Claude, Cohere)
- Test sync with various library sizes
- Test playlist generation with different queries
- Test error scenarios (no internet, wrong credentials, etc.)
- Test concurrent operations (sync while generating playlist)
- Test state persistence across page refreshes
- Document all test results
- Create testing checklist for all features
- Recruit beta tester if possible
- Test as if you're a new user
- Can you complete setup without documentation?
- Can you generate your first playlist in under 5 minutes?
- Test all features systematically
- Try to break the UI with unexpected inputs
- Test edge cases (empty library, no API key, etc.)
- Test with slow network connection
- Verify all error messages are helpful
- Check for any visual glitches or layout issues
- Test accessibility (keyboard navigation, screen readers if possible)
- Document all bugs found
- Update main README.md with UI section
- Add installation instructions for UI extras
- Document how to launch UI (
plexmix ui) - Add screenshots of all main pages
- Create UI user guide section
- Explain each page's purpose and features
- Document keyboard shortcuts
- Add troubleshooting section for common issues
- Document UI-specific configuration options
- Create CHANGELOG entry for UI release
- Update pyproject.toml version
- Add UI extras to package metadata
- Review all code for consistency
- Ensure consistent naming conventions
- Check all imports are necessary
- Remove any commented-out code
- Ensure all TODOs are addressed or documented
- Review error handling across all modules
- Check all user-facing text for clarity and grammar
- Verify all links and buttons work
- Test production build
- Build with
reflex exportif applicable - Test deployed version
- Get feedback from peer review if possible
- Address any final issues
Deliverable: Production-ready UI with comprehensive testing and documentation
- All CLI features are accessible via UI
- Configuration changes work bidirectionally (CLI <-> UI)
- Background tasks can be monitored and cancelled
- No data loss or corruption occurs
- Error messages are clear and actionable
- All 6 main pages are fully functional
- Page load time < 2 seconds
- Search results appear in < 500ms
- UI remains responsive during background tasks
- Handles libraries with 10,000+ tracks smoothly
- No memory leaks during extended use
- New user can complete setup in < 10 minutes
- User can generate first playlist in < 5 minutes
- Interface is intuitive without documentation
- Works on tablets and desktops (responsive)
- Keyboard shortcuts improve power user experience
These features are not in scope for the initial release but are noted for future development:
- Embed audio preview player in UI
- Play tracks directly from track listings
- Control Plex playback from UI (if API supports)
- Visualize mood trends over time
- Track playlist generation history with charts
- Show most-used tags and genres
- Library growth over time graph
- Playlist templates (save and reuse mood queries)
- Smart playlists (auto-update based on tag rules)
- Collaborative playlists (share with other users)
- Playlist scheduling (auto-generate at intervals)
- Duplicate track detection and removal
- Dark mode theme switcher
- Customizable color schemes
- Drag-and-drop file upload for M3U import
- Bulk track operations (batch delete, edit)
- Export to other services (Spotify, YouTube Music)
- Touch-optimized controls for mobile
- Progressive Web App (PWA) support for offline access
- Mobile-specific layouts
- Push notifications for completed tasks
- User authentication and accounts
- User-specific playlists and settings
- Sharing playlists between users
- Permission levels (admin, user, guest)
To begin implementation:
# Checkout the UI branch
git checkout feature/reflex-ui
# Install UI dependencies
poetry add reflex@^0.6.0
poetry install -E ui
# Start with Phase 1
# Follow TODO items sequentially
# Test as you go
plexmix ui
# When complete, merge to main
git checkout master
git merge feature/reflex-uiGood luck with the implementation!