Development
EXEPERT is a hybrid monorepo: several independently deployed applications share
one repository, but they do not all belong to one package-manager workspace.
The root pnpm-workspace.yaml includes the AI Lab root and services/dsh-sidecar.
The website, Brain Learning Lab, identity gateway, and docs keep their own
package manifests, lockfiles, build commands, and deployment boundaries.
Application map
MASTER-exe/
|-- src/ + api/ app.exepert.com (AI Lab, API, auth, CMS)
|-- apps/
| |-- landing/ www.exepert.com (website and blog)
| |-- brain-learning/ learn.exepert.com (learning application)
| `-- auth-gateway/ auth.exepert.com (gated identity gateway)
|-- services/
| `-- identity-runtime/ portable Better Auth composition
`-- docs-site/ app.exepert.com/docs (this documentation)
| Surface | Start from the repository root | Local address |
|---|---|---|
| AI Lab | pnpm.cmd dev | http://localhost:9001 |
| Website and blog | pnpm.cmd landing:dev | http://localhost:3001 |
| Brain Learning Lab | bun --cwd=apps/brain-learning run dev | http://127.0.0.1:3012 |
| Documentation | pnpm.cmd --dir docs-site exec docusaurus start | http://localhost:3000 |
The Brain Learning package is deliberately outside the root pnpm workspace.
Run its Bun commands from apps/brain-learning or use Bun's --cwd option;
running the root pnpm dev starts app.exepert.com, not the learning site.
Human Brain Learning Lab
Use the fast path when dependencies and prepared assets already exist:
Set-Location '.\apps\brain-learning'
bun run dev
Open http://127.0.0.1:3012 after Vite reports that it is ready. The port is
fixed and strict, so Vite stops with an error instead of silently selecting a
different port.
For a fresh checkout or after dependency changes, install from the package's pinned Bun lockfile first:
Set-Location '.\apps\brain-learning'
bun install --frozen-lockfile
bun run dev
Vite provides hot module replacement for the React, TypeScript, and CSS UI.
The repository already contains the public anatomy and prepared MRI assets used
by the development server. Ordinary UI/UX work does not require a .env file,
Supabase, Vercel, Cloudflare, or a Hugging Face runtime. Lessons, quizzes,
simulation, 3D/MRI views, downloads, and guest progress remain available, with
progress stored only in the current browser.
The plain Vite server does not emulate Cloudflare Pages Functions. Its
/api/session request therefore falls back to the application's
session-unavailable state; this does not block device-local learning. Use the
Pages emulator when the UI needs the production API boundary:
python -m pip install -r requirements-mri.txt
bun run build
bunx wrangler@4.130.0 pages dev dist --port 8788
Open http://127.0.0.1:8788 for that build. The build verifies and prepares the
pinned MRI inputs and therefore needs network access. CI uses Bun 1.3.14 and
Python 3.11; the deployment workflow pins Wrangler 4.130.0.
wrangler.toml keeps IDENTITY_ENABLED=false and TUTOR_ENABLED=false, so
local Pages emulation must not be treated as an authenticated release.
UI/UX source map
| Path | Primary responsibility |
|---|---|
apps/brain-learning/src/App.tsx | Page structure, learning flow, comparison dashboard, quizzes, and experiment UI. |
apps/brain-learning/src/styles.css | Visual system, responsive layout, controls, focus states, and reduced-motion behavior. |
apps/brain-learning/src/Viewer.tsx | Three.js anatomy, exploded structures, labels, outlines, and camera controls. |
apps/brain-learning/src/MriViewer.tsx | MRI slice rendering and comparison interaction. |
apps/brain-learning/src/content.ts | Chapters, audience tracks, activities, questions, sources, and limitations. |
AI Lab browser application
Start the root dev server:
pnpm dev
pnpm dev runs three steps in order (from package.json):
"dev": "pnpm run build:wasm && pnpm run build:vanilla-logger && vite"
build:wasm: compilesrust/brain_simto WebAssembly viawasm-pack.build:vanilla-logger: bundles the diagnostics logger into a standalone IIFE for the legacy reference pages (see Diagnostics Logger and Reference Pages).vite: starts the Vite dev server on port 9001.
Open http://localhost:9001 once Vite reports it is ready.
Keyboard shortcuts
The shortcuts are registered in src/events.ts:
| Key | Action |
|---|---|
Space | Toggle simulation pause. |
A | Toggle the grid helper. |
S | Toggle the axis helper. |
The diagnostics panel adds one more, handled in src/diag/logger.ts:
| Key | Action |
|---|---|
Ctrl + Shift + L | Toggle the in-app diagnostics panel. |
Hot reload
Vite handles HMR for the TypeScript and CSS. Changes to the Rust code are
not hot-reloaded: rerun pnpm run build:wasm (or restart pnpm dev) to pick up
simulation changes.
AI Lab commands
| Command | Description |
|---|---|
pnpm dev | Start dev server (builds WASM + vanilla logger, then Vite HMR) |
pnpm build | Full production build (WASM + vanilla logger + Vite) |
pnpm preview | Preview production build locally on port 9001 |
pnpm typecheck | Run TypeScript type checking (no emit) |
pnpm test | Run unit tests (Vitest) |
pnpm test:watch | Run tests in watch mode |
pnpm test:e2e | Run Playwright end-to-end tests |
pnpm test:e2e:ui | Run Playwright tests with UI |
pnpm search:index | Populate Typesense search indexes |
pnpm supabase:start | Start local Supabase stack |
pnpm supabase:stop | Stop local Supabase stack |
pnpm supabase:reset | Reset local database |
pnpm supabase:diff | Generate migration diff |
pnpm supabase:push | Push migrations to remote |
pnpm supabase:gen-types | Regenerate TypeScript types from schema |
Documentation site
cd docs-site
pnpm install
pnpm start # Live-editing dev server at http://localhost:3000
pnpm build # Production build, including the local search index
pnpm serve # Serve the production build
pnpm preview:search # Build, serve, and verify local search
When the app runs from a local origin such as http://localhost:9001, the
top-nav Docs button and in-app help links default to the Docusaurus dev server
at http://localhost:3000. Start both servers when you want the app and docs to
work side by side locally.
The docs search box uses @easyops-cn/docusaurus-search-local. pnpm start
is useful for editing layout and content, but it does not serve the generated
search index. To test search, run pnpm build followed by pnpm serve, or use
pnpm preview:search.
Troubleshooting stale AI Lab content
If changes don't appear after saving:
- Hard refresh the browser:
Ctrl+Shift+R - Clear Vite cache:
npx vite --force - Full clean rebuild:
pnpm build - Check terminal: if the Vite process crashed, restart with
pnpm dev
Security note for shared AI Lab servers
vite.config.ts sets server.fs.allow: ['..'] and binds the dev server on port
9001 with no authentication. That is convenient locally because the build serves
sibling reference directories, but it means anyone who can reach the port can
read files from the parent directory. Do not expose the dev server on a public
or shared network as-is. For sharing a build, use the static output from
pnpm build behind your own server instead.
Typesense Search Indexer (Plan 008)
When Typesense is configured, populate or refresh the search indexes:
pnpm search:index
This runs scripts/typesense-index.mjs, which connects to Typesense (using
TYPESENSE_ADMIN_KEY + VITE_TYPESENSE_HOST from .env), drops and recreates
the traces_spans and docs collections, then bulk-imports data from Supabase
and docs-site/docs/**/*.md. The script auto-loads .env so it works without
the --env-file flag on Node < 20.6. Requires admin credentials in .env.