An AI-fabric topology planner: given a switch capability model, a scale (compute nodes and NICs/GPUs per node), and constraints (subscription, link speeds, tiers), it computes a feasible Clos / rail-optimized fabric, validates it, and renders / exports it. It also ships an AMD MI3XX reference "advisor" that recommends a design from a GPU count.
The code is layered so the planning engine is fully headless (usable from the browser and a CLI), and the viewers are independent components that render purely from the engine's output model.
src/
core/ # headless engine (no DOM) — the Input->Output calculator
types.ts # contracts: SwitchSpec, TopologyInput, TopologyModel, Kpis,
# FabricGraph, ValidationReport, Advisor, Viewer
engine.ts # generate(input) -> model, port math, builders, KPIs, AMD data
validate.ts # validate(model) -> ValidationReport (radix, coverage, cabling...)
advisors/ # Advisor plugin registry
amdReference.ts # AMD MI3XX reference design advisor
index.ts # listAdvisors() / getAdvisor(id)
index.ts # public barrel
exporters/
format.ts # pure toDot / toSlurmConf (no DOM) — reused by the CLI
dom.ts # browser download / print-to-PDF
index.ts
viewers/ # independent components; consume ONLY a TopologyModel
viewer2d.ts # createViewer2D() {mount,update,destroy} + renderModelSvg()
viewer3d.ts # createViewer3D() (WebGL, model-driven)
index.ts
ui/
store.ts # tiny observable store + connectViewer() (auto-render seam)
cli/
index.ts # topogen CLI
topology.js / renderer.js / exporters.js / flow3d.js / main.js
# back-compat barrels + the live browser controller
Data flow:
TopologyInput --> core.generate() --> TopologyModel --> validate() --> ValidationReport
|
+----------------------+----------------------+
v v v
Viewer2D Viewer3D exporters (DOT/Slurm/SVG/JSON)
Advisor.recommend({gpus, variant, family}) maps a GPU count to a partial
TopologyInput (plus matched reference metadata) that is fed to generate().
The rigorous Input/Output shapes live in src/core/types.ts. A new switch only
needs to provide a SwitchSpec (id, asic, kind, radixBySpeed, and — for DDC
NCPs — a fixed nifPorts/fabricPorts split) to be planned with.
validate(model) returns a ValidationReport { ok, checks[], errors[], warnings[] }
covering: leaf radix feasibility, spine fan-in vs radix, endpoint coverage,
cable-count consistency, switch-count consistency, connectivity, and
oversubscription advisories. The engine attaches it as model.report.
npm run cli -- --leaf as9817_64d --topology fat2 --nodes 64 --gpn 8 \
--down 400 --up 800 --blocking 0.862 --formats dot,slurm,svg,json --out ./out
npm run cli -- --advisor amd-mi3xx --gpus 2048 --variant tree --family sched --out ./out
Writes the requested formats, prints the validation report, and exits non-zero if the design is infeasible.
Requires Docker or Podman. The app listens on port 8778 by default; override with
PORT=<port> if that port is busy.
make dev # hot-reload dev server — http://localhost:8778
make build # build production image (nginx + static dist/)
make up # run production container in background
make run # build + run production container in foreground
make stop # stop running containers
make logs # follow production container logsmake dev mounts the repo into a Node 20 container, runs npm install, then
npm run dev with --host 0.0.0.0. Source edits on the host are picked up by
Vite without rebuilding the image.
make build runs a multi-stage Dockerfile: Vite builds dist/, then nginx serves
it. make up / make run expose the app at http://localhost:8778.
Pushes to main run .github/workflows/pages.yml:
npm ci → npm run build (with BASE_PATH=/<repo>/) → deploy dist/ to GitHub Pages.
One-time setup in the repo on GitHub:
- Settings → Pages → Build and deployment → Source → GitHub Actions
- After the first successful workflow run, the site is live at
https://<org-or-user>.github.io/topogen/
Local preview of the Pages build:
BASE_PATH=/topogen/ npm run build && npm run previewnpm run dev/npm run build— Vite web app (same as insidemake dev/ the Docker build stage).npm test— Node test runner (viatsx); includes golden characterization tests.npm run typecheck—tsc --noEmit.npm run golden— regeneratetest/fixtures/golden.json(only when a change is intended).
Offline note: Three.js is vendored at src/vendor/three.module.js and loaded
locally (no CDN). The container harness scripts/run.sh runs any npm script in a
Node container when npm is unavailable on the host.
- The engine (
core/engine.ts) carries a transitional// @ts-nocheck; contracts intypes.tsare strict. Fine-grained decomposition of the engine and removal of@ts-nocheckis staged. main.jsremains the live browser controller (UX unchanged). Theui/store.tsobservable is in place for incremental migration of panels/viewers onto it.
