The Electron + React desktop client for NVIDIA Personal AI Router.
For what PAIR is, how to install it, and how to set it up, start at the repository root README and the Getting started guide. This file covers only what you need to work in this directory.
src/electron/ Main process: broker supervision, service bridge, IPC
src/preload/ Typed preload bridge (window.pairApi, window.windowApi)
src/ui/ React renderer
src/shared/ Types and utilities shared across the three above
src/declarations/ Ambient type declarations
scripts/ Build, license, and contract tooling
tests/ Vitest unit tests
docs/ Desktop-specific architecture and contract documentation
The renderer reaches services only through the preload bridge; it never talks to
a Go worker directly. Electron starts nvpair-ui-broker and the broker
supervises every other worker.
npm install
npm startnpm start compiles the Go binaries from the sibling ../services directory
into cli-bin/, then launches Electron. Prerequisites, with versions and download
links, are listed under
Prerequisites.
Four checks, all runnable from this directory:
npm run lint # ESLint, including Prettier formatting
npm run typecheck # main, renderer, and test tsconfigs
npm test # unit tests
npm run service-contracts:check # this app still agrees with ../servicesRun all four before opening a merge request. npm run format applies formatting
rather than just reporting it.
npm run test:unit:watch # re-runs on save
npm run test:unit tests/modular/x.test.ts # one file
npm run test:unit:coverage # coverage plus a summary
npm run test:clean # clears the Vitest cache and stray tmpdirsTests live in tests/, not beside the source. tests/fixtures/isolation.ts is
loaded for every test and blocks non-loopback Axios requests; it does not
intercept other network clients. It sets PAIR_USER_DATA to a per-worker temp
directory only when the variable is unset, and tests may override it.
assertIsolated() is opt-in; tests that touch the file-config-store should call
it. Avoiding writes to real app data also depends on tests injecting a
PathProvider via initPlatform that honors PAIR_USER_DATA. Axios tests
needing HTTP should use a local fake.
Coverage includes src/shared/**, src/ui/utils/**, src/ui/constants/**, and
the selected Electron files src/electron/csp.ts, src/electron/globals.ts,
src/electron/inference-demo-schedule.ts, and src/electron/redact-log.ts.
Most of the Electron main process and renderer modules remain outside the
configured coverage set.
vitest.config.ts also declares an e2e project, but it selects no files. There
is no end-to-end suite yet; nothing exercises the app together with its service
processes.
service-contracts:check compares this app's bridge against the JSON-RPC surface
of ../services and fails on drift. Run it whenever you touch a method, payload,
or push event. If the Go surface changed legitimately, regenerate the record:
npm run service-contracts # report drift
npm run service-contracts:write # regenerate docs/services-api.mdChanging the services themselves also means running their own tests — see services testing.
npm run build # renderer, main, preload, and CLI bundlesThis produces the bundles the application runs from, for use on the machine that built them. Installable builds come from the releases page.
Everything specific to the application is in docs/:
- Architecture — processes, IPC, and state flow
- Frontend API — preload surface and push channels
- Services backend integration — service contract and update procedure
- Services parity — current capability status
- Services API — generated JSON-RPC method surface
Contribution workflow, security policy, and support live at the repository root: CONTRIBUTING.md, SECURITY.md, and SUPPORT.md.