Date: 2026-03-05
Branch: feature/api-spec-update
Migrate the current Tauri application into a browser-first web application while preserving core user flows:
- Browse themes and schedules
- Play media prompts
- Record audio responses
- Store pending recordings locally
- Upload recordings reliably
This migration is feasible.
A direct "compile current Rust/Tauri layer to WASM" approach is not a drop-in path because the current backend layer depends on:
- Tauri command runtime (
#[tauri::command],AppHandle,State) - Native filesystem paths (
app_data_dir) - Native SQLite (
rusqlite) - Native plugin-based recording integration
The frontend currently calls these Tauri commands:
delete_filedelete_recordingdownload_mediafetch_schedulefetch_schedulesfetch_themesfix_client_idsget_api_base_urlget_recordingsinsert_test_recordingread_file_as_base64save_recordingupload_pending_recordings
Use a platform adapter layer in TypeScript so app pages/hooks do not call invoke(...) directly.
Define one interface (for example PlatformApi) and provide two implementations:
TauriPlatformApifor existing app behaviorWebPlatformApifor browser behavior
- API calls: use
fetchagainst existing backend endpoints inopenapi.json - Local storage for recordings and metadata: IndexedDB
- Audio recording: browser
MediaRecorder - Media playback: direct
/v1/media/{filename}URL orfetch+ blob URL when needed - Background uploads: periodic timer plus online-state retry
fetch_themes,fetch_schedules,fetch_schedule:- Replace with direct HTTP
GETcalls to/v1/theme,/v1/schedule,/v1/schedule/{schedule_id}.
- Replace with direct HTTP
get_api_base_url:- Replace with env config (
VITE_API_BASE_URL).
- Replace with env config (
download_media:- Replace with direct media URL loading and optional browser cache handling.
read_file_as_base64,delete_file:- Remove native file dependency; use in-memory
BlobfromMediaRecorderand convert as needed.
- Remove native file dependency; use in-memory
save_recording:- Replace with web save flow:
- Keep recording blob + metadata in IndexedDB as pending item.
- Replace with web save flow:
get_recordings,delete_recording,insert_test_recording:- Replace with IndexedDB operations.
upload_pending_recordings:- Replace with web upload queue worker that posts to
/v1/upload, then uploads to returned presigned URL.
- Replace with web upload queue worker that posts to
fix_client_ids:- Replace with one-time IndexedDB migration script for old local entries.
- Phase 1: Introduce platform abstraction
- Add
src/platform/PlatformApi.tsinterface. - Add
src/platform/tauriPlatformApi.tswrapper over existinginvokecalls. - Update pages/hooks to depend on the interface instead of direct
invoke. - Keep behavior unchanged.
- Phase 2: Web read-only flows
- Add
src/platform/webPlatformApi.tswith HTTP implementations for themes/schedules/media. - Add runtime platform selection.
- Verify routes
/themes,/schedule/:id/start,/schedule/:idwork in browser mode.
- Phase 3: Web recording pipeline
- Implement
MediaRecorder-based capture in web adapter. - Store recording blobs + metadata in IndexedDB.
- Preserve duration tracking and client ID behavior.
- Phase 4: Upload queue and resiliency
- Implement periodic pending upload in web mode.
- Retry on reconnect and transient failures.
- Add cleanup and deletion logic for successfully uploaded items.
- Phase 5: Tests and hardening
- Add unit tests for platform adapters.
- Add integration tests for recording lifecycle and upload queue behavior.
- Verify parity with Tauri flows (including fake YLE media behavior).
- Phase 6: Optional Rust/WASM extraction
- Identify pure Rust logic worth sharing (for example audio processing utilities).
- Move pure logic to a separate crate without Tauri dependencies.
- Compile that crate to WASM only if performance or reuse justifies complexity.
- Browser build runs without Tauri runtime.
- No direct
@tauri-apps/api/*imports remain in page-level components/hooks used by web runtime. - User can complete full flow in browser:
- open theme
- open schedule
- record audio
- see local pending recordings
- upload pending recordings
- Existing Tauri mode still works.
-
Risk: Browser recording MIME/container differences across platforms.
-
Mitigation: Normalize supported MIME types and validate server expectations.
-
Risk: Offline queue inconsistency.
-
Mitigation: Use deterministic IndexedDB schema and idempotent upload state transitions.
-
Risk: CORS or auth policy mismatch for browser requests.
-
Mitigation: Add explicit backend CORS policy for deployed web origin(s).
- Build the
PlatformApiinterface and Tauri adapter first. - Replace direct
invoke(...)usage in:
src/App.tsxsrc/pages/ThemesPage.tsxsrc/pages/ScheduleStartPage.tsxsrc/pages/SchedulePage.tsxsrc/pages/DetailsPage.tsxsrc/pages/TestPage.tsxsrc/hooks/useAutoUpload.tssrc/hooks/useRecording.tssrc/utils/mediaUrl.ts
- Add the web adapter and switch based on runtime.
- Implement IndexedDB storage and upload queue.
- Add tests and run parity verification.
- Replacing backend API design
- Full offline-first PWA feature set
- Immediate Rust-to-WASM conversion of Tauri command layer