ADR 0001: React + FastAPI Architecture

Status

Accepted

Date

2024-01-15

Context

FUSION is a Python-based optical network simulator that currently uses a CLI interface. We want to add a graphical user interface to:

  • Allow users to configure and run simulations without CLI knowledge

  • Provide real-time monitoring of long-running simulations

  • Enable browsing and downloading of output artifacts

  • Visualize network topology and results

Constraints:

  • Primary use is local, single-user, no accounts/auth required

  • Simulations run from minutes to weeks

  • Users should not need to install Node.js

  • We may add HPC job submission in the future

  • Browser-based UI is acceptable (no desktop app requirement)

Options Considered:

  1. React SPA + FastAPI backend - Web UI served by Python

  2. Electron desktop app - Native app with embedded Chromium

  3. Tauri desktop app - Rust-based native wrapper

  4. PyQt5/PySide6 - Native Python GUI

  5. PyQt5 WebEngine - Embedded web view in Qt

Decision

We will use React SPA + FastAPI backend architecture.

The FastAPI server:

  • Serves the pre-built React static files

  • Provides REST API for CRUD operations

  • Streams real-time updates via Server-Sent Events (SSE)

  • Manages simulation subprocesses

The React frontend:

  • Built with Vite, TypeScript, and Tailwind CSS

  • Uses TanStack Query for server state management

  • Ships pre-built inside the Python wheel

Rationale

Why React + FastAPI?

Factor

React + FastAPI

Electron

Tauri

PyQt5

Qt WebEngine

Bundle size

~5MB static

200MB+

20MB+

Varies

Varies

User install

pip install

Download installer

Download installer

pip install

pip install

Node.js needed

No (pre-built)

Yes (dev)

Yes (dev)

No

No

Cross-platform

Yes

Yes

Yes

Issues

Issues

Modern UI

Excellent

Excellent

Excellent

Limited

Requires web skills

Developer pool

Large

Large

Small

Small

Small

HPC extensibility

Excellent

Poor

Poor

Poor

Poor

Key advantages of React + FastAPI:

  1. Zero user friction: pip install fusion[gui] then fusion gui. No Node.js, no Electron download, no native installers.

  2. Clean subprocess isolation: Long-running simulations in separate processes. If a simulation crashes or leaks memory, the server remains stable.

  3. Future HPC support: REST API naturally extends to remote job submission. The same UI can talk to local or remote backends.

  4. Modern developer experience: React and FastAPI are industry-standard with excellent documentation, tooling, and developer availability.

  5. Easy updates: Update Python package, get new UI automatically. No separate app update mechanism.

Why NOT Electron/Tauri?

  • Installation complexity: Users must download and run installers, deal with OS security warnings, manage separate update mechanisms.

  • Bundle size: Electron bundles entire Chromium (~200MB). Tauri is smaller but requires Rust toolchain for development.

  • Network model: Desktop apps connecting to Python backend adds complexity. Browser already knows how to talk HTTP.

  • Not needed: We don’t need desktop integration (system tray, file associations). Browser on localhost is fine.

Why NOT PyQt5?

  • UI quality: Building modern, responsive UIs in Qt is harder than in React. Qt widgets look dated without significant effort.

  • Cross-platform issues: PyQt5 has platform-specific bugs, especially on macOS. WebEngine is particularly problematic.

  • Developer expertise: Web developers are more common than Qt developers.

Consequences

Positive

  • Simple installation and distribution

  • Modern, maintainable frontend codebase

  • Clear separation between UI and backend

  • Easy to add features (API endpoints + UI components)

  • Familiar technology for most developers

Negative

  • Two build systems (Python + Node.js for development)

  • Need to bundle built React in Python wheel

  • Browser-based, so no deep OS integration

  • SSE reconnection needs handling for long sessions

Neutral

  • Monorepo structure with frontend/ directory

  • Developers may open subfolders in different IDEs

  • Need pre-commit hooks for both Python and JS linting

Implementation Notes

  1. Static file serving: FastAPI serves React build from fusion/api/static/. SPA fallback ensures deep links work.

  2. Process management: Simulations run as subprocesses in new process sessions (start_new_session=True). This enables clean cancellation of entire process trees.

  3. Real-time updates: SSE for logs and progress. File-based IPC (stdout to file, tail for streaming) avoids pipe buffer deadlocks.

  4. Build pipeline: CI builds frontend, copies to fusion/api/static/, then builds Python wheel. Users get pre-built UI.