Backend / Frontend Runtime Model

Niamoto GUI runs in two main modes.

Development mode

In development:

  • the React app runs through the Vite dev server

  • the FastAPI backend runs separately

  • Vite proxies /api/* calls to FastAPI

This gives:

  • hot module replacement on the frontend

  • backend auto-reload during Python development

  • a clear separation between UI assets and API behavior

Typical workflow:

./scripts/dev/dev_web.sh test-instance/niamoto-nc

Or manually:

uv run python scripts/dev/dev_api.py --instance test-instance/niamoto-nc
cd src/niamoto/gui/ui && pnpm dev

Packaged mode

In packaged or end-user mode:

  • the frontend is pre-built into static assets

  • FastAPI serves both the API and the frontend bundle

  • Node.js is not required for end users

The build output used for this mode is:

  • src/niamoto/gui/ui/dist

Desktop runtime

When running through a desktop shell:

  • the same frontend is embedded inside the native application window

  • packaged desktop mode loads the UI from the loopback FastAPI server on 127.0.0.1

  • the shell waits for an authenticated /api/health probe before navigating to that loopback origin

  • runtime metadata exposes both mode (web or desktop) and shell (tauri, electron, or null)

  • local fonts are loaded from public/fonts instead of Google Fonts

  • the welcome screen and project selection flow are especially relevant

Current shells:

  • Tauri remains the production desktop shell

  • Electron exists as a parallel experimental shell under electron/

The shell-neutral desktop contract now includes:

  • a shared renderer bridge for project selection, settings, external URLs, and desktop-only helpers

  • a shared project-selection config path through NIAMOTO_DESKTOP_CONFIG

  • shell-specific settings, logs, and application identifiers kept separate

Development entry points:

./scripts/dev/dev_desktop.sh test-instance/niamoto-nc
./scripts/dev/dev_electron.sh test-instance/niamoto-nc

Both shells follow the same high-level startup model:

  1. show a lightweight native loading state

  2. launch the Python sidecar on loopback

  3. wait for the authenticated health probe to return the expected desktop token

  4. navigate the window to Vite in hot-reload mode, or to the packaged FastAPI loopback origin otherwise

What to separate when you document or change the GUI

Keep these layers distinct:

  • backend API concerns

  • frontend state and routing concerns

  • runtime-specific behavior for desktop mode

Users see one product. The code does not live in one layer.