Skip to content

Architecture

Phytograph runs as three cooperating processes inside one packaged binary:

                         packaged .app / .exe
┌────────────────────────────────────────────────────────────────┐
│                                                                │
│  Electron main process (Node)                                  │
│  ┌─────────────────────────────────┐                           │
│  │  main.ts                        │                           │
│  │   └─ backend.ts                 │                           │
│  │       └─ spawns ────────────────┼──► phytograph_backend     │
│  │   └─ ipc.ts (handlers)          │     (PyInstaller bundle)  │
│  │   └─ updater.ts                 │   (dynamic port)          │
│  └─────────────────────────────────┘             ▲             │
│           ▲                                      │ HTTP        │
│           │ IPC (contextBridge)                  │ (fetch)     │
│           ▼                                      │             │
│  ┌─────────────────────────────────┐             │             │
│  │  Preload (preload.ts)           │             │             │
│  │   exposes window.electronAPI    │             │             │
│  └─────────────────────────────────┘             │             │
│           ▲                                      │             │
│           │                                      │             │
│  ┌─────────────────────────────────┐             │             │
│  │  Renderer (React, Chromium)     ├─────────────┘             │
│  │   - HTTP for data               │                           │
│  │   - electronAPI for OS stuff    │                           │
│  └─────────────────────────────────┘                           │
└────────────────────────────────────────────────────────────────┘

Read the rest of this section in order:

  1. Processes & IPC — what each process is responsible for and the narrow bridge between them.
  2. Backend Sidecar — how the Python sidecar is built, supervised, and addressed.
  3. Version Lock — the three-way version contract that keeps the supervisor and backend in sync.

Why a Python sidecar instead of native bindings

The bulk of the scientific stack (open3d, scipy) ships as Python wheels; PyHelios is built from a source submodule (see Backend) so the Helios C++ core can be co-developed. Bundling them via PyInstaller is the fastest path to a shippable cross-platform build. Native Helios bindings beyond PyHelios are a future direction (would skip Python for hot paths) but not on the current roadmap.

Why Electron over Tauri

This is the second-generation desktop shell; the first was Tauri. The migration is complete and Tauri is retired. Electron was chosen for richer renderer debugging tools and to avoid Rust-side complexity in a project where the heavy compute is in Python anyway.