Completion Date: January 6, 2026
Status: Build successful, ready for testing
Phase 2B successfully implements a comprehensive web UI for monitoring and controlling sync operations. Users can view real-time sync progress, trigger manual syncs, and review sync history through an intuitive Blazor interface.
File: src/SpotifyTools.Web/Controllers/SyncController.cs
Four REST endpoints for sync management:
Returns current sync status or "Idle" if no sync is active.
- Response:
SyncStatusDtowith phase progress details - Use case: Real-time progress monitoring in UI
Returns paginated sync history records.
- Response:
List<SyncHistoryDto> - Default: Last 20 syncs, ordered by most recent
- Includes: Tracks/artists/albums added, duration, status
Returns the most recent successful sync.
- Response:
SyncHistoryDtoor null - Use case: "Last synced" display on dashboard
Triggers a new sync operation (Full or Incremental).
- Request:
{ "SyncType": "Full" | "Incremental" } - Response: 202 Accepted (sync runs in background)
- Validation: Rejects if sync already in progress
File: src/SpotifyTools.Web/DTOs/SyncStatusDto.cs
Clean API contracts for sync data:
- SyncStatusDto - Current sync status with phase progress
- PhaseProgressDto - Individual phase (tracks/artists/albums/playlists) progress
- SyncHistoryDto - Historical sync record with metrics
- StartSyncRequest - Request body for triggering syncs
File: src/SpotifyTools.Web/Pages/SyncStatus.razor
Interactive page with real-time updates:
- ✅ Real-time progress monitoring - Auto-refreshes every 5 seconds when sync active
- ✅ Phase progress bars - Visual progress for tracks/artists/albums/playlists
- ✅ Status badges - Color-coded status indicators (Success, InProgress, Failed, etc.)
- ✅ Rate limit handling - Displays rate limit reset time
- ✅ Error display - Shows last error per phase
- ✅ Manual sync triggers - Buttons to start Incremental or Full sync
- ✅ Sync history table - Last 10 syncs with metrics
- ✅ Responsive design - Bootstrap 5 styling
- ✅ Success/error alerts - User feedback for actions
Current Status Card:
- Shows active sync with phase-by-phase progress
- Displays "Idle" with last sync info when no active sync
- Progress bars with percentage complete
- Rate limit warnings
Sync History Table:
- Sync type (Full/Incremental) badges
- Started timestamp (local time)
- Duration (formatted: 15s, 2.5m, 1.2h)
- Status with color-coded badges
- Tracks added/updated counts
- Artists/Albums/Playlists added
// Runs in background while page is open
while (true)
{
await Task.Delay(5000); // 5 seconds
if (currentStatus.IsActive)
{
await LoadStatusSilently();
StateHasChanged();
}
}File: src/SpotifyTools.Web/Pages/Start.razor
Added "Sync Status" card to home page:
- Icon: Rotating arrow (bi-arrow-repeat)
- Description: "Monitor library synchronization and trigger manual syncs"
- Links to
/syncroute - Matches design of existing Library and Analytics cards
File: src/SpotifyTools.Web/Program.cs
Registered required services:
builder.Services.AddScoped<ISyncStateRepository, SyncStateRepository>();
builder.Services.AddScoped<IRateLimitTracker, RateLimitTracker>();
builder.Services.AddScoped<IncrementalSyncOrchestrator>();- Navigate to home page (http://localhost:5241/start)
- Click "Sync Status" card
- See current sync status or "No active sync"
- If sync active, see phase-by-phase progress with percentages
- On Sync Status page, click "Start Incremental Sync" or "Start Full Sync"
- Success message appears: "Incremental sync started successfully"
- Page auto-refreshes to show progress
- Progress bars update every 5 seconds
- Completion shows in history table
- Start a full sync (may take 30-45 minutes)
- Progress bars show current phase and percentage
- Can leave page and return - status persists in database
- Rate limits show countdown timer if hit
- Errors displayed per phase if any occur
curl http://localhost:5241/api/sync/statusResponse (Idle):
{
"status": "Idle",
"isActive": false
}Response (Active):
{
"syncHistoryId": 123,
"startedAt": "2026-01-06T11:00:00Z",
"status": "InProgress",
"isActive": true,
"tracksProgress": {
"status": "Success",
"currentOffset": 500,
"totalItems": 500,
"itemsProcessed": 500,
"percentComplete": 100
},
"artistsProgress": {
"status": "InProgress",
"currentOffset": 150,
"totalItems": 300,
"itemsProcessed": 150,
"percentComplete": 50
}
}curl -X POST http://localhost:5241/api/sync/start \
-H "Content-Type: application/json" \
-d '{"syncType": "Incremental"}'curl http://localhost:5241/api/sync/history?page=1&pageSize=5Syncs run in background tasks via Task.Run():
_ = Task.Run(async () =>
{
await _orchestrator.RunFullSyncAsync();
});- Controller returns immediately (202 Accepted)
- Sync continues in background
- Progress tracked in database via SyncState
- UI polls for updates every 5 seconds
All sync state persists across app restarts:
- sync_history table tracks completed syncs
- sync_state table tracks in-progress phases
- UI always shows accurate status from database
- API errors return 500 with error message
- UI displays errors in alert boxes
- Phase-level errors shown in progress details
- Rate limits displayed with countdown timer
- Page loads without errors
- "No active sync" displays when idle
- Last sync info shows correctly
- History table loads with data
- Incremental sync trigger works (requires running app)
- Full sync trigger works (requires running app)
- Progress updates in real-time (requires active sync)
- Auto-refresh works (verify every 5 seconds)
- Rate limit message displays (requires hitting limit)
- Error messages display (requires sync failure)
- Chrome/Edge - verify layout
- Firefox - verify layout
- Safari - verify layout
- Mobile responsive - test on phone
# Test status endpoint
curl http://localhost:5241/api/sync/status
# Test history endpoint
curl http://localhost:5241/api/sync/history
# Test last sync endpoint
curl http://localhost:5241/api/sync/last-sync
# Test trigger (when no sync active)
curl -X POST http://localhost:5241/api/sync/start \
-H "Content-Type: application/json" \
-d '{"syncType": "Incremental"}'Four warnings about <RenderPhaseProgress> not recognized as component:
- Cause: RenderFragment pattern not recognized by Razor compiler
- Impact: None - works correctly at runtime
- Fix: Convert to separate component file (future enhancement)
- Currently no way to cancel in-progress sync via UI
- Can only wait for completion or restart app
- Future: Add
POST /api/sync/cancelendpoint
When Phase 2C (Enhanced Incremental Sync) is complete:
- Add "Last Synced" timestamp to UI
- Show "Sync now" vs "Scheduled in X minutes"
- Display incremental sync metrics separately
- Add auto-sync toggle switch
Instead of 5-second polling, use SignalR:
- Server pushes updates when progress changes
- Instant UI updates (no delay)
- Lower server load (no polling)
Add settings panel:
- Enable/disable auto-sync
- Configure sync interval
- Set rate limit thresholds
- Choose what to sync (tracks only, full, etc.)
New Files (3):
src/SpotifyTools.Web/Controllers/SyncController.cs(~250 lines)src/SpotifyTools.Web/DTOs/SyncStatusDto.cs(~60 lines)src/SpotifyTools.Web/Pages/SyncStatus.razor(~450 lines)
Modified Files (2):
src/SpotifyTools.Web/Program.cs(added DI registrations)src/SpotifyTools.Web/Pages/Start.razor(added sync status card)
Total New Code: ~760 lines
All deliverables met. Web UI now provides comprehensive sync monitoring and control. Ready for user testing and Phase 2C (Enhanced Incremental Sync).
Next Steps:
- Start SpotifyTools.Web:
cd src/SpotifyTools.Web && dotnet run - Navigate to http://localhost:5241/sync
- Test sync triggering and progress monitoring
- Review sync history table
- Proceed with Phase 2C when ready