Rewrite frontend to Tauri v2 + Svelte 5 for cross-platform support #4

Merged
jknapp merged 5 commits from feature/tauri-rewrite into main 2026-04-06 20:45:10 +00:00
Owner
Summary

Rewrites the desktop frontend from PySide6/Qt to Tauri v2 + Svelte 5, following the same architecture as https://repo.anhonesthost.net/MacroPad/voice-to-notes. This enables native
cross-platform support for Windows, macOS, and Linux with proper installers.

What changed

- Headless Python backend (backend/) — Extracts all orchestration logic from MainWindow into AppController, exposes a FastAPI REST API + WebSocket control channel. No PySide6 dependency.
- Tauri v2 shell (src-tauri/) — Minimal Rust scaffolding with shell, dialog, and process plugins. Configured for sidecar launch of the Python backend.
- Svelte 5 frontend (src/) — Complete UI with reactive stores, dark theme, and all settings from the original Qt GUI. Components: Header, StatusBar, Controls, TranscriptionDisplay,
Settings (full 10-section modal).
- Gitea CI/CD (.gitea/workflows/) — Two workflows: release.yml builds Tauri app installers (.msi, .dmg, .deb/.rpm) on all platforms; build-sidecar.yml builds Python sidecar with CUDA+CPU
variants.
- Headless PyInstaller spec (local-transcription-headless.spec) — Simplified build config that excludes PySide6, producing a leaner sidecar binary.
- Updated docs — README.md and CLAUDE.md fully rewritten for the new architecture.

Architecture

Tauri App (user launches this)
└─ Spawns Python backend as sidecar
├─ FastAPI REST API (/api/*)
├─ WebSocket /ws/control (real-time state + transcriptions)
├─ OBS web display at localhost:8080
└─ Transcription engine (Whisper or Deepgram)

What's preserved

- The legacy PySide6 GUI (main.py, gui/) still works unchanged
- All Python backend code (client/, server/) is untouched
- OBS browser source at localhost:8080 continues to work
- Configuration format and storage (~/.local-transcription/config.yaml) is unchanged

Build verification

- Svelte frontend: npx vite build passes (70KB JS + 11KB CSS)
- Tauri Rust: cargo check passes
- Python backend: syntax validated, all files clean

Test plan

- Run headless backend: uv run python -m backend.main_headless and test API with curl
- Run Tauri dev mode: npm run tauri dev (requires system deps)
- Verify legacy GUI still works: uv run python main.py
- Verify OBS display at http://localhost:8080
- Test CI workflows after merge (requires BUILD_TOKEN secret)
- Test on Windows, macOS, Linux
--- Summary Rewrites the desktop frontend from PySide6/Qt to Tauri v2 + Svelte 5, following the same architecture as https://repo.anhonesthost.net/MacroPad/voice-to-notes. This enables native cross-platform support for Windows, macOS, and Linux with proper installers. What changed - Headless Python backend (backend/) — Extracts all orchestration logic from MainWindow into AppController, exposes a FastAPI REST API + WebSocket control channel. No PySide6 dependency. - Tauri v2 shell (src-tauri/) — Minimal Rust scaffolding with shell, dialog, and process plugins. Configured for sidecar launch of the Python backend. - Svelte 5 frontend (src/) — Complete UI with reactive stores, dark theme, and all settings from the original Qt GUI. Components: Header, StatusBar, Controls, TranscriptionDisplay, Settings (full 10-section modal). - Gitea CI/CD (.gitea/workflows/) — Two workflows: release.yml builds Tauri app installers (.msi, .dmg, .deb/.rpm) on all platforms; build-sidecar.yml builds Python sidecar with CUDA+CPU variants. - Headless PyInstaller spec (local-transcription-headless.spec) — Simplified build config that excludes PySide6, producing a leaner sidecar binary. - Updated docs — README.md and CLAUDE.md fully rewritten for the new architecture. Architecture Tauri App (user launches this) └─ Spawns Python backend as sidecar ├─ FastAPI REST API (/api/*) ├─ WebSocket /ws/control (real-time state + transcriptions) ├─ OBS web display at localhost:8080 └─ Transcription engine (Whisper or Deepgram) What's preserved - The legacy PySide6 GUI (main.py, gui/) still works unchanged - All Python backend code (client/, server/) is untouched - OBS browser source at localhost:8080 continues to work - Configuration format and storage (~/.local-transcription/config.yaml) is unchanged Build verification - Svelte frontend: npx vite build passes (70KB JS + 11KB CSS) - Tauri Rust: cargo check passes - Python backend: syntax validated, all files clean Test plan - Run headless backend: uv run python -m backend.main_headless and test API with curl - Run Tauri dev mode: npm run tauri dev (requires system deps) - Verify legacy GUI still works: uv run python main.py - Verify OBS display at http://localhost:8080 - Test CI workflows after merge (requires BUILD_TOKEN secret) - Test on Windows, macOS, Linux
jknapp added 5 commits 2026-04-06 20:44:56 +00:00
New files:
- client/deepgram_transcription.py — DeepgramTranscriptionEngine with
  managed mode (proxy) and BYOK mode (direct Deepgram). Sends raw binary
  PCM audio over WebSocket, handles both proxy and Deepgram response formats.

Modified files:
- config/default_config.yaml — Replace remote_processing with new remote
  section (mode, server_url, auth_token, byok_api_key, deepgram_model, language)
- client/config.py — Add migration from old remote_processing config
- gui/settings_dialog_qt.py — Replace Remote Processing group with
  Transcription Mode section (Local/Managed/BYOK radio buttons, login/register
  dialogs, balance display, model selector)
- gui/main_window_qt.py — Select engine based on remote.mode config,
  add error and credits_low handlers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Scaffold the cross-platform rewrite from PySide6/Qt to Tauri + Svelte,
following the same architecture as voice-to-notes. The Python backend
runs headless as a sidecar, with a FastAPI control API that the Svelte
frontend connects to via REST and WebSocket.

New files:
- backend/app_controller.py: Headless orchestration (extracted from MainWindow)
- backend/api_server.py: FastAPI control endpoints + /ws/control WebSocket
- backend/main_headless.py: Headless entry point for sidecar mode
- src-tauri/: Tauri v2 Rust shell with sidecar and dialog plugins
- src/: Svelte 5 frontend (App, Settings, Controls, TranscriptionDisplay)
- src/lib/stores/: Reactive stores for backend connection, config, transcriptions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two workflows adapted from voice-to-notes:

- release.yml: Builds the Tauri app shell (.deb/.rpm for Linux, .msi
  for Windows, .dmg for macOS) on push to main. Auto-bumps version,
  creates Gitea release, uploads platform binaries.

- build-sidecar.yml: Builds the headless Python backend sidecar via
  PyInstaller when client/server/backend code changes. Produces CUDA
  and CPU variants for Linux/Windows, CPU-only for macOS. Uses the new
  local-transcription-headless.spec (no PySide6 dependencies).

Also adds local-transcription-headless.spec — a simplified PyInstaller
config for the headless backend that excludes all Qt/PySide6 imports.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update both docs to reflect the new architecture:
- Tauri v2 + Svelte 5 frontend replacing PySide6/Qt
- Headless Python backend with FastAPI control API
- Cross-platform support (Windows, macOS, Linux)
- Deepgram remote transcription (managed/BYOK)
- Gitea CI/CD workflows for automated builds
- New project structure with backend/, src/, src-tauri/
- Updated development commands and build instructions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The src/lib/ directory was being excluded by a Python .gitignore rule
for lib/ (meant for Python's build output). Changed to /lib/ so it
only matches root-level lib/ and doesn't block src/lib/.

Adds 8 files that were created but missed in the initial commit:
- 5 Svelte components (Header, StatusBar, Controls, TranscriptionDisplay, Settings)
- 3 TypeScript stores (backend, config, transcriptions)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jknapp merged commit c9db43d56c into main 2026-04-06 20:45:10 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: streamer-tools/local-transcription#4