Technology
Invariants first, then a frame rate
The design rule is that a rendered number must be traceable to a stored row in one hop. Everything below exists to make that rule hard to break by accident.
Architecture
Eight rules the implementation is not allowed to break
Each of these is enforced in code, and each has a journey or an audit check behind it rather than a paragraph of intent.
SurrealDB is the sole authority
There is no cache that is allowed to be right. If the store and a projection disagree, the projection is wrong, and the out-of-band watcher exists precisely to notice that somebody edited the database behind our back.
One transaction, one journal row
A write, its entity.version bump, its atlas_event journal row and the workspace.lastSeq allocation happen inside one BEGIN … COMMIT. A committed change cannot be missing its journal row; a rolled-back change cannot burn a sequence number.
The stream invalidates, never asserts
Server-sent events carry a journal seq and nothing else. The client re-reads its authoritative scope, which makes duplicated, reordered or dropped notifications harmless rather than corrupting.
One snapshot contract
GET /api/graph feeds the 3D scene, the 2D graph, the spatial scene and the table; metric tiles run the same deterministic functions over the same rows. A picture and a number cannot drift apart.
Layout never blocks the frame clock
d3-force-3d runs in a Web Worker and the scene renders on frameloop="demand" — frames are produced for interaction, a live change, or while the layout settles. Settled positions are cached per scope.
The model never holds SQL
The assistant selects from a fixed tool set and every query plan is validated against the stored ontology before it runs. An answer that cites an object outside the retrieved set is reported as a degraded state, not dressed up as a model failure.
Loopback by default
The API binds 127.0.0.1 with trustProxy: false. Public reach comes from a tunnel that overwrites CF-Connecting-IP at the edge, so a visitor cannot claim to be local in order to gain a write.
Honest truncation
Node order is deterministic — by object type, then uid, then degree — so the busiest context survives a cap, and truncated plus totalMatchingNodes say out loud when the cap bit.
Measured 2026-10-17
Targets, results, and the machine they came from
One Apple M5 Max workstation, 128 GB, with the inference engine sharing the same box. Reproduce any row with the command under the table.
| Measure | Target | Measured | Verdict |
|---|---|---|---|
| Bounded graph query | under 500 ms after warm-up | p50 88 ms · p95 101 ms · max 103 ms | MET |
| Commit → visible in an open tab | p95 under 1 s at ~10 updates/s | p50 1 ms · p95 104 ms · max 104 ms, converged 20/20 | MET |
| Interaction floor | 45 FPS on the settled scene | p50 59.9 fps · p05 59.5 | MET |
| End-to-end journey suite | every journey green | 85/85 end-to-end checks | MET |
| Offline behaviour | no non-local requests attempted | verified with internet blocked | MET |
| Test suite | All green before publish | 62 pass / 0 fail, 2 skipped of 64 · 85 checks / 0 failures across 9 journeys · measured 2026-10-18 | MET |
Reproduce the store counts without touching the UI: curl -s -u "$SURREAL_USERNAME:$SURREAL_PASSWORD" -H "Surreal-NS: spectra" -H "SURREAL-DB: atlas" --data-binary "SELECT workspaceId, count() AS c FROM entity GROUP BY workspaceId" http://127.0.0.1:18180/sql
Validation
What has to pass before a number is published
nine end-to-end journeys over the real HTTP surface, plus the integration suite. Both were run on this machine and re-read from their own reports, measured 2026-10-18 with node tools/run-tool.mjs test and node tests/e2e/run.mjs. Latency and frame-rate rows below stay quoted from docs/VALIDATION.md and carry that document’s date.
Restart persistence
Committed entities and relations are readable through an independent path into the store, not just from a warm process.
Native graph truth
Relation records carry real record links and answer a traversal — the edges are not a UI array replayed back at us.
One snapshot, four views
An API create, update and delete converges the scene, table, inspector and metrics with no reload, and a node that stops matching leaves the filtered graph.
No dangling edges
Removing a node removes its relationships from the rendered snapshot, and a mutation racing the initial load is not lost.
Version conflict and idempotency
Two previews of the same constrained stock cannot both reserve it; a replayed commit does not duplicate and a rejected action writes nothing.
Scope protection
Cross-workspace reads, evidence, actions and live updates are all refused — the same guarantee the public read-only URL depends on.
Measured offline with the internet blocked: the application cold-boots, the service panel reports real state, and a copilot question was answered in 15.06 s with zero non-local requests attempted. This site holds to the same rule — it makes no request outside nodavx.com.
Stack
Everything here, with its licence read from the installed manifest
Versions and licences were not copied from a website. They were read out of node_modules/*/package.json and surreal version on the serving machine.
| Component | Version | Role | Licence |
|---|---|---|---|
| SurrealDB | 3.2.3 | Authoritative store — documents, graph links and vector in one engine | Business Source License; verify current terms before redistribution |
| @surrealdb/node | 3.1.0 | Official TypeScript client | Apache-2.0 |
| Fastify | 5.12.7 | HTTP surface, cookie session, content-type parsing | MIT |
| zod | 4.6.7 | Every inbound payload and every contract | MIT |
| React / React DOM | 19.3.1 | Application shell and panels | MIT |
| three.js | 0.186.1 | WebGL scene | MIT |
| @react-three/fiber + drei | 9.8.2 / 10.7.9 | React renderer for three.js and its helpers | MIT |
| d3-force-3d | 3.0.6 | Force layout, executed inside a Web Worker | MIT |
| Vite | 8.3.4 | Build and dev server | MIT |
| Tailwind CSS | 4.3.3 | Application UI styling (the marketing site uses none of it) | MIT |
| TypeScript | 5.9.3 | Typechecked with --noEmit; Node runs the source directly | Apache-2.0 |
| puppeteer-core | 25.14.0 | Browser harness for the journey suite and this site’s QA | Apache-2.0 |
| Node.js | v24.21.0 | Runtime for the API, the harnesses and this builder | Apache-2.0 |
| cloudflared | 2026.10.1 | Public reach without opening a port on the house network | Cloudflare, open source |
| Space Grotesk / Inter / JetBrains Mono | — | Typefaces on this site, self-hosted as woff2 subsets | SIL Open Font License 1.1 |
| Natural Earth | 110m | Coastline and populated-place data behind the hero artwork | Public domain |
Unverified
Six things this build does not claim
A measured page is only worth reading if it also says what it did not measure.
Answer quality is not graded. Grounding is machine-proved — citations resolve to retrieved records — but nobody scores the prose. Inference on this Mac has taken 15.2 s to 54.3 s depending on load.
Frame figures come from headless Chrome with an emulated camera drag. Trackpad feel, label legibility and contrast still need human eyes; the narrow viewport is checked for "renders", not for comfort.
No latency is measured at the expanded-scope cap (1,000 nodes / 3,000 edges) or against the 10k/30k stress fixture.
One JavaScript bundle with no code-splitting. Fine on loopback; over a real network the first paint will be slower than the numbers here suggest.
/health reports the database version as unknown, while the binary is 3.2.3. Cosmetic, and still a lie in a status page.
Single-user local POC: a signed actor/role/workspace cookie, no TLS of its own, no multi-tenant story.
Read the documents behind this page
Architecture, live-state protocol, ontology, operations, validation and the roadmap are all shipped as plain markdown, and the site links to the exact copies it was written from.