Skip to content

Frontend Overview

The YAPTIDE frontend is a React single-page application that provides a 3D simulation editor, job management, and result visualization. It runs entirely in the browser, with optional in-browser Python and Geant4 runtimes.

ComponentTechnology
FrameworkReact (TypeScript)
3D engineThree.js
UI kitMUI + Emotion
HTTP clientky (fetch wrapper)
AuthKeycloak JS SDK (OIDC)
Python in browserPyodide + comlink (Web Worker)
Geant4 in browserGeant4 WebAssembly (Web Worker)
Result renderingJSRoot
Build systemCreate React App + react-app-rewired
TestingJest + React Testing Library

The frontend uses neither Redux/Zustand nor React Router:

  • State management: React Context providers arranged in a deeply-nested ServiceTree (composition pattern). Each service exposes a custom hook.
  • Navigation: A custom TabPanel system driven by string state. No URL-based routing.

App.tsx composes the entire application:

ConfigProvider
└─ ThemeProvider + SnackbarProvider
└─ KeycloakAuth
└─ Store (YaptideEditor instance)
└─ Geant4DatasetContextProvider
└─ DialogProvider
└─ Auth
└─ RemoteWorkerSimulationContextProvider
└─ PythonConverterService
└─ Geant4LocalWorkerSimulationContextProvider
└─ Loader
└─ WrapperApp (the actual UI)

Each provider creates a React Context exposing a hook:

ContextHookPurpose
ConfigProvideruseConfig()Backend URL, demo mode, deployment flags
StoreuseStore()YaptideEditor instance, tracked jobs, results
AuthuseAuth()Login/logout, authKy (authenticated HTTP client)
KeycloakAuthuseKeycloakAuth()Keycloak SSO state
PythonConverterServiceusePythonConverter()In-browser JSON→input file conversion
LoaderuseLoader()Load projects from files/URLs/JSON

WrapperApp.tsx renders a tab bar with these panels:

TabComponentPurpose
loginLoginPanelUsername/password or Keycloak SSO
editorEditorPanel3D scene editor (main working area)
examplesExamplesPanelLoad pre-built example simulations
simulationsSimulationsPanelView/manage submitted jobs
inputFilesInputFilesPanelInspect generated simulator input files
resultsResultsPanelVisualize simulation results (JSRoot plots)
aboutAboutPanelCredits and version info
src/
├── App.tsx # Service tree composition
├── config/
│ └── ConfigService.tsx # Environment variable config
├── services/
│ ├── AuthService.tsx # Auth context + hook
│ ├── StoreService.tsx # Editor + job state
│ ├── LoaderService.tsx # Project loading
│ ├── KeycloakAuthService.tsx
│ ├── RemoteWorkerSimulationContextProvider.tsx
│ └── Geant4LocalWorkerSimulationContextProvider.tsx
├── ThreeEditor/
│ ├── js/
│ │ ├── YaptideEditor.js # Core editor class (~780 lines)
│ │ ├── EditorContext.ts # Context switching (geometry/scoring/settings)
│ │ └── viewport/ # 4-way split viewport
│ ├── Simulation/
│ │ ├── Figures/ # BoxGeometry, SphereGeometry, etc.
│ │ ├── Zones/ # BooleanZone CSG operations
│ │ ├── Detectors/ # Scoring detector types
│ │ ├── Physics/ # Beam, physics settings
│ │ └── Materials/ # Material definitions
│ └── components/
│ └── Sidebar/ # EditorSidebar (Geometry/Scoring/Settings tabs)
├── PythonConverter/
│ ├── PythonWorker.ts # Pyodide Web Worker
│ └── PythonConverterService.tsx # React context wrapping the worker
├── Geant4Worker/ # Geant4 Wasm Web Worker
├── JsRoot/ # JSRoot result visualization
├── WrapperApp/ # Tab navigation + panels
├── libs/
│ └── converter/ # Git submodule → converter repo
└── util/ # Shared utilities

The 3D editor uses the signals library for internal event propagation. Over 40 signals cover events like:

  • objectAdded, objectRemoved, objectChanged
  • zoneGeometryChanged, scoringQuantityChanged
  • editorCleared, sceneGraphChanged

React bridges these signals via useSignal hooks to trigger re-renders.

All editor mutations (add figure, move object, change material) go through a Command pattern for undo/redo support. See Adding Commands.

The editor JSON format captures the full simulation state. It is:

  • Auto-saved to localStorage on every change
  • Exportable as .json files
  • Sent to the backend for simulation submission
  • Consumed by the Pyodide converter for input file generation

The project uses Create React App with react-app-rewired for Webpack customization (config-overrides.js):

  • react-dnd ESM compatibility fixes
  • .cjs/.mjs module resolution
  • Ignoring geant4_wasm.wasm from bundling
  • Ignoring node:worker_threads