Boot sequence
The app boots from src/main.ts. The module order matters: the diagnostics
logger is imported first so any boot-time error is captured.
import './diag/logger'
import './brain-ui'
import './events'
import { scene, initRendering } from './scene'
import { createRenderer } from './renderer'
import { loadAllAssets } from './loaders'
import { createBrain } from './brain'
import { initGui } from './gui'
import { runLoop } from './run'
The async boot() function then runs:
async function boot(): Promise<void> {
const { renderer, backend } = await createRenderer()
initRendering(renderer, backend)
const assets = await loadAllAssets()
const brain = await createBrain(assets, renderer, backend)
;(window as any).neuralNet = brain
console.log(`[EXEPERT Brain] Travel backend: ${brain.travelBackend}`)
const loadingEl = document.getElementById('loading')
if (loadingEl) loadingEl.style.display = 'none'
scene.add(brain.meshComponents)
initGui(brain)
runLoop(brain)
}
Step by step
- Diagnostics logger (
src/diag/logger.ts): imported first. It patchesconsole.*, installserror/unhandledrejectionhandlers, and mounts the floating panel. See Diagnostics Logger. - Renderer (
src/renderer.ts):createRenderer()returns aWebGLRendererand the'webgl2'backend tag. - Scene (
src/scene.ts):initRendering()attaches the canvas, sets up the camera,OrbitControls,Stats, helpers, and the on-canvas status bar. - Assets (
src/loaders.ts):loadAllAssets()loads the brain OBJ mesh and the electric sprite texture, returning the extracted vertices. - Brain (
src/brain.ts):createBrain()initializes the WASM module, constructs theWorldfrom the vertices, and builds the neuron, axon, and particle geometry bound to WASM memory. - Global handle: the
Brainis stashed onwindow.neuralNetfor the UI and any external integrations. - Scene attach + GUI: the brain meshes are added to the scene and
initGui()mounts the lil-gui panel. - Run loop:
runLoop(brain)starts therequestAnimationFrameloop.
If boot() rejects, the catch handler logs the error and hides the loading
overlay so the failure is visible rather than stuck on a spinner.
Lazy-loaded modules
After boot() completes, several UI modules are loaded via requestIdleCallback
(or setTimeout fallback) so they don't block the first frame:
requestIdleCallback(() => import('./ui/search-box').then((m) => m.mountSearchBox()))
requestIdleCallback(() => import('./ui/prompt-playground').then((m) => {
return m.mountPromptPlayground()
}))
Each module is responsible for its own readiness checks. If a module's backend
is unavailable (missing env vars, missing tables, etc.), it disables itself
gracefully: no visible panel is mounted, and a console.warn is emitted.
| Module | Mount guard |
|---|---|
workbench | Wires immediately; always responds. Activity-bar buttons switch views. Prompts view lazy-loads prompt-playground. |
search-box | Skips if Typesense env vars are unset. |
prompt-playground | Passive mount skips if Supabase is unconfigured, the prompts table query fails, or the active project's prompt registry is empty. The Prompts activity-bar button opens the right-side panel on demand regardless. |
Prompt Playground preflight
mountPromptPlayground() now renders its DOM shell immediately (including a loading
spinner), then fetches listPrompts(getActiveProject().id). If the query fails
(Supabase unconfigured, RLS error, network failure), an inline error message
replaces the spinner. If the query returns zero rows and the call was not
forceOpen, the playground closes itself. This means users always see a visual
response: never a blank area.
A Prompts button in the far-left activity bar (#activityPromptsTrigger) allows
users to open the playground on demand, even when the registry is empty. Clicking
the button triggers openPromptsView() in workbench.ts, which lazy-imports
prompt-playground.ts and calls mountPromptPlayground({ forceOpen: true }).
This shows the right-side playground card with a + New button so the first prompt
can be created. The trigger uses the currently active project from
getActiveProject(), so prompt data is scoped to the project the user is viewing.