4.5 KiB
Raw Permalink Blame History

Architecture Decision Record: Use Tauri with Embedded Node for Cross-Platform App

Date: 2025-08-15 Status: Accepted Decision Makers: [Team/Project Name] Context: Desktop + Mobile App Development


Context

We are building a cross-platform application targeting desktop (Windows, macOS, Linux) and mobile (Android, iOS) using SvelteKit + TailwindCSS for the UI.

Key goals:

  • Maintain fast development iteration with hot reload for both frontend and backend logic.
  • Allow backend logic to be written in TypeScript for developer familiarity and speed.
  • Support writing performance-critical features in Rust if needed.
  • Deploy the same codebase across desktop and mobile with minimal divergence.
  • Avoid security limitations of browser-only apps (e.g., CORS, sandbox restrictions).
  • Provide direct access to Node APIs and/or Rust commands for native capabilities.

Decision

We will use Tauri v2 with an embedded Node runtime alongside the SvelteKit frontend.

graph LR
%% "Tauri + Node + SvelteKit + Tailwind Architecture"

subgraph "Frontend (UI)"
  SvelteKit["SvelteKit<br/>(TS + TailwindCSS)"]
  WebView["WebView<br/>(Tauri Runtime)"]
  SvelteKit --> WebView
end

subgraph "Backend Logic"
  NodeJS["Embedded Node.js Runtime<br/>(TypeScript backend)"]
  Rust["Rust Commands<br/>(Tauri APIs / Native modules)"]
end

subgraph "Platforms"
  Desktop["Desktop<br/>(Windows, macOS, Linux)"]
  Mobile["Mobile<br/>(Android, iOS)"]
end

WebView -->|IPC / API calls| NodeJS
WebView -->|Tauri Commands| Rust
NodeJS -->|FFI / API bridge| Rust
Rust -->|Native APIs| Desktop
Rust -->|Native APIs| Mobile
WebView --> Desktop
WebView --> Mobile

Why Tauri:

  • Small runtime compared to Electron for desktop builds (~520 MB without Node).
  • Native integration with OS features (system tray, notifications, file access, etc.).
  • Built-in support for mobile (Android/iOS) in Tauri v2.
  • Strong security model and long-term community backing.

Why embed Node:

  • Node.js runtime allows full access to existing npm ecosystem and built-in modules (fs, crypto, net, etc.).
  • Enables backend logic to be written entirely in TypeScript during early development.
  • Hot reload with tools like nodemon or ts-node for fast iteration.
  • Flexibility to migrate specific logic to Rust incrementally without losing productivity.

Workflow:

  • Development:

    • Run SvelteKit dev server for UI (npm run dev)
    • Run Node backend with hot reload
    • Tauri shell points to localhost dev server for instant updates
  • Production:

    • Bundle SvelteKit output with adapter-static or adapter-node
    • Include Node runtime for backend logic
    • Optionally replace parts of backend with compiled Rust commands for performance-critical paths

Alternatives Considered

  1. Capacitor

    • Mature mobile ecosystem and simpler dev workflow for mobile
    • No built-in Node runtime; would require rewriting backend logic as plugins or browser-safe code
    • We would lose direct access to Node APIs without extra complexity
  2. Electron

    • First-class Node integration
    • Larger desktop build size (50150 MB)
    • Heavier memory footprint compared to Tauri
  3. Pure Tauri (Rust backend only)

    • Smallest build sizes, fastest runtime
    • Slower development for backend logic without TS hot reload
    • Would require Rust expertise for all backend features from day one

Consequences

Positive:

  • Full-stack TypeScript possible in early development → faster MVP delivery.
  • Incremental migration path to Rust for performance-sensitive features.
  • Single codebase for desktop & mobile.
  • Rich native API access via both Node and Tauris Rust plugins.
  • Security benefits from Tauris isolation model.

Negative:

  • Larger mobile builds (~2540 MB vs. Capacitors ~1020 MB).
  • More complex tooling setup (Rust + Node + mobile SDKs).
  • Slightly slower startup time on mobile due to Node runtime initialization.

References


I can also add a diagram showing the architecture — frontend, embedded Node backend, and optional Rust modules — so stakeholders can visually understand how the stack fits together across platforms.

Do you want me to make that diagram next?