Skip to content

Repository files navigation

NiChart Electron

Desktop launcher for NiChart — wraps the NiChart React SPA and optionally manages a local NiChart FastAPI server via Docker.

Built with Electron 31, electron-vite 2, and React 18.

This repository is currently a work in progress. You are free to use it with the understanding that it will change rapidly and things may break. When it is ready for wider distribution, this README will start with more concise instructions to download, install and run it.


Architecture

┌──────────────────────────────────────────────────────┐
│  Electron launcher (this repo)                       │
│  ┌────────────┐  ┌──────────────┐  ┌─────────────┐  │
│  │ Setup      │  │ Dashboard    │  │ NiChart     │  │
│  │ wizard     │  │ (server ctrl)│  │ window      │  │
│  └────────────┘  └──────────────┘  └──────┬──────┘  │
│                                           │          │
│  Local HTTP server (loopback)  ←──────────┘          │
│  serves resources/renderer/ (NiChart SPA)            │
└──────────────────────────────────────────────────────┘
          │ API calls (http)
          ▼
  Cloud / Remote server  OR  local Docker container

Three operating modes are configured on first launch:

Mode What it does
Cloud Connects to the hosted NiChart service (no local setup)
Remote Points at a user-provided API server URL; optional SSH tunnel for HPC clusters
Local Starts a NiChart API Docker container on this machine

Prerequisites

Tool Version Notes
Node.js ≥ 20 (v24 confirmed) Use nvm or nvm-windows
yarn 1.x npm install -g yarn — npm can also be used
Git any
Docker Desktop any Required only for Local mode

Windows + VS Code note: VS Code sets ELECTRON_RUN_AS_NODE=1 on all child processes. Running electron-vite directly with this variable set breaks Electron. The yarn dev script routes through scripts/dev.mjs, which strips the variable before spawning electron-vite. Always use yarn dev, not npx electron-vite dev.


Development Setup

# 1. Clone and install
git clone <repo-url>
cd NiChart_Electron
yarn install

# 2. Start the dev server
yarn dev

This builds the main process and preload scripts, then starts:

  • A Vite HMR dev server for the launcher UI (React)
  • The Electron window pointed at that dev server

Hot reload: The launcher UI (Setup wizard, Dashboard) hot-reloads on save. Changes to src/main/ or src/preload/ require restarting (Ctrl+C, then yarn dev again).

Dev without a real NiChart SPA

resources/placeholder/ contains a minimal fallback page served when the NiChart window is opened in dev mode. This lets you test the launcher flow without a full SPA build.

Placing a real SPA for local testing

Build the NiChart React SPA and copy its dist/ output into resources/renderer/:

# In the NiChart SPA repo:
yarn build

# Then copy the output:
cp -r dist/* /path/to/NiChart_Electron/resources/renderer/

The SPA will be picked up automatically on next launch. In dev mode the launcher falls back to the placeholder; change getNiChartRendererBase() in src/main/index.ts temporarily if you want to test with the real SPA in dev.

SPA integration point

The Electron preload (src/preload/nichart.ts) injects the API URL before any SPA JavaScript runs:

// window.__NICHART_CONFIG__ is set before <script> tags execute
const apiUrl =
  (window as any).__NICHART_CONFIG__?.apiUrl ??
  import.meta.env.VITE_API_URL ??   // fallback for standalone dev
  'http://localhost:8000'

Add this to the SPA's API config module. No build-time changes needed when embedding in Electron.


Configuration (first run)

On first launch the Setup wizard guides you through three steps:

  1. Mode — Cloud / Remote / Local
  2. Configure — varies by mode:
    • Cloud: accept the data-privacy consent
    • Remote: enter the API server URL; optionally enable SSH tunnel (host, port, user, key)
    • Local: choose a backend (Docker on Windows; Docker/Singularity/Apptainer/SLURM on Linux/Mac), pass prerequisites check, set data directory and port
  3. Done — settings are saved to the OS user-data directory via electron-store

Click Settings in the Dashboard header at any time to re-run the wizard.

SSH tunnel (Remote mode)

When the remote API server is not directly reachable (e.g. an HPC login node), the launcher can forward a local port over SSH:

ssh -N -L 127.0.0.1:<localPort>:<remoteApiHost>:<remoteApiPort> <user>@<sshHost>

The tunnel uses your system ssh binary and existing credentials (ssh-agent or ~/.ssh/config). Keys protected by a passphrase require ssh-agent to be running.


Building for Distribution

Before building, place the NiChart SPA build in resources/renderer/ and set the production API URL:

// src/shared/constants.ts
export const CLOUD_API_URL = 'https://nichart.cbica.upenn.edu'  // real URL

Also confirm the Docker image name in resources/docker/docker-compose.yml.

Build commands

# Compile TypeScript (output → out/)
yarn build

# Package for the current platform
yarn dist

# Platform-specific
yarn dist:win     # Windows → dist/NiChart-Setup-<version>.exe  (NSIS)
yarn dist:mac     # macOS  → dist/NiChart-<version>.dmg
yarn dist:linux   # Linux  → dist/NiChart-<version>.AppImage

Cross-platform builds require the target OS or a CI environment. The packaged installer embeds the Electron binary, compiled JS, and the SPA — it does not embed Docker images or the API server.

Release checklist

  • Set CLOUD_API_URL in src/shared/constants.ts
  • Set real Docker image name in resources/docker/docker-compose.yml
  • Copy the NiChart SPA build into resources/renderer/
  • Bump version in package.json
  • yarn build && yarn dist:<platform>
  • Test the installer on a clean machine (Docker Desktop installed, no dev tools)
  • Publish installer to GitHub Releases or internal channel
  • Push the latest API image to your Docker registry

See DISTRIBUTION.md for detailed notes on the three-layer update model (Electron app / React SPA / Docker image) and the electron-updater auto-update setup.


Project Structure

src/
  main/
    index.ts          # App lifecycle, SPA HTTP server, window management
    ipc.ts            # All IPC handlers (server, tunnel, config, prereqs)
    server.ts         # ServerManager — docker compose start/stop/health
    ssh-tunnel.ts     # SshTunnelManager — SSH port-forward lifecycle
    config.ts         # electron-store wrapper (AppConfig persistence)
    prerequisites.ts  # System checks (docker, singularity, etc.)
  preload/
    index.ts          # contextBridge API for the launcher UI
    nichart.ts        # Injects window.__NICHART_CONFIG__ into the NiChart window
  renderer/src/
    pages/
      Setup.tsx       # First-run wizard (mode → consent/backend/prereqs → configure)
      Dashboard.tsx   # Main screen (server/tunnel controls, Open NiChart button)
    App.tsx           # Root — switches between Setup and Dashboard on firstRun flag
  shared/
    types.ts          # AppConfig, ServerStatus, TunnelStatus, etc.
    constants.ts      # CLOUD_API_URL

resources/
  docker/
    docker-compose.yml  # Bundled compose file (uses Docker Hub image)
  placeholder/          # Dev fallback page for the NiChart window
  renderer/             # ← NiChart SPA build goes here (git-ignored)

scripts/
  dev.mjs             # Strips ELECTRON_RUN_AS_NODE before spawning electron-vite

FastAPI-config/
  .env.local.template # Reference .env template for the API container

Troubleshooting

ELECTRON_RUN_AS_NODE / blank window on yarn dev Always launch with yarn dev, not directly via npx electron-vite dev or node_modules/.bin/electron-vite dev. See the note under Prerequisites.

ERR_PACKAGE_PATH_NOT_EXPORTED from electron-vite Occurs when something tries to require.resolve('electron-vite/bin/...'). scripts/dev.mjs resolves the binary path directly — do not change that approach.

Docker containers keep stopping / health check fails Check yarn dev terminal for docker compose output. Ensure Docker Desktop is running and WSL2 is available (Windows). The logs panel in the Dashboard also shows compose stdout/stderr live.

SSH tunnel not connecting

  • Check that ssh <user>@<host> works in a terminal without a passphrase prompt (add the key to ssh-agent first: ssh-add ~/.ssh/id_ed25519)
  • The SSH log panel in the Dashboard (click the tunnel status chip) shows raw stderr from the SSH process
  • StrictHostKeyChecking=accept-new is set, so the first connection will accept and cache the host key automatically

About

Electron app that handles installation of NiChart components and is usable as a desktop application. Configurable to use cloud, remote server, or local processing.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages