SDK and packages
The Nimbus repository is two ecosystems in one tree: a Rust workspace under
crates/ that builds the server binary, and an npm monorepo under
packages/ that holds everything JavaScript — the SDK your app imports,
the compatibility wrappers, the code generator, and the admin UI. This page
explains how the JavaScript side is structured and why none of it ships
through the public npm registry.
Two things named “nimbus”
Section titled “Two things named “nimbus””The name appears on both sides of the repo, and they are different artifacts:
packages/nimbusis the JavaScript SDK — the npm package@nimbus/nimbusthat application code imports.crates/nimbusis the Rust facade crate for embedders. Itscrates/nimbus/src/lib.rsre-exports the stable high-level surface of the internal workspace crates (core types, the engine, the runtime contract) so a Rust program embedding Nimbus depends on one crate instead of several internal ones.
When this documentation says “the SDK” it always means the JavaScript package. The Rust facade is an embedding surface, not a client library.
The package map
Section titled “The package map”The npm workspace (declared in the root package.json) contains seven
packages:
| Package | npm name | Role |
|---|---|---|
packages/nimbus | @nimbus/nimbus | Canonical JavaScript SDK |
packages/convex | convex | Convex compatibility wrapper |
packages/codegen | @nimbus/codegen | Code generator behind nimbus codegen |
packages/nimbus-ui | nimbus-ui | Admin UI embedded into the server binary |
packages/firebase | @nimbus/firebase | Firebase-style app + Firestore client |
packages/mongodb | @nimbus/mongodb | Connection-string helper for the MongoDB surface |
packages/dynamodb | @nimbus/dynamodb | Client-config helper for the DynamoDB surface |
Every one of them is marked "private": true. None is published to the
public npm registry — see the distribution model
below for how they reach applications instead.
The canonical SDK: packages/nimbus
Section titled “The canonical SDK: packages/nimbus”@nimbus/nimbus is the single canonical JavaScript implementation. It is
ESM-only, ships TypeScript sources directly, and exposes six entry points
(the exports map in packages/nimbus/package.json):
| Entry point | What it owns |
|---|---|
@nimbus/nimbus | The Nimbus root client — the control-plane resources client for services, sandboxes, and sessions |
@nimbus/nimbus/server | Function builders (query, mutation, action, httpAction, …), defineSchema/defineTable, HTTP router |
@nimbus/nimbus/values | Value and validator types shared between server and clients |
@nimbus/nimbus/browser | Data-plane clients: NimbusClient (WebSocket), NimbusHttpClient, NimbusReactClient |
@nimbus/nimbus/transports/rest | The REST transport (NimbusRestClient) used by the root client |
@nimbus/nimbus/react | React bindings: NimbusProvider, useQuery, useMutation, usePaginatedQuery, … |
react and react-dom are optional peer dependencies, needed only for
the /react entry point. The full API surface is documented in the
SDK reference; this page only places the package in the
architecture.
The Convex wrapper: packages/convex
Section titled “The Convex wrapper: packages/convex”The repo’s rule is that packages/nimbus is the canonical implementation
and packages/convex stays a thin compatibility layer. Reading its
sources shows what “thin” means in practice:
packages/convex/src/server.tsimports the canonical builders from@nimbus/nimbus/server(query,mutation,defineSchema, …) and re-exports them under the Convex API names and types.packages/convex/src/react.tsbuilds Convex’s React surface (ConvexProvider,useQuery, …) directly onNimbusProviderand the@nimbus/nimbus/reacthooks.packages/convex/src/browser.tswraps theNimbusClient,NimbusHttpClient, andNimbusReactClientclasses from@nimbus/nimbus/browserbehind Convex client names such asConvexReactClient.packages/convex/src/values.tsis the one place with local logic: it implements Convex’sv.*validator vocabulary as lightweight validator descriptors rather than re-exporting, because the shapes are Convex-specific.
The package also carries a small convex CLI shim
(packages/convex/src/cli.mjs) whose codegen subcommand delegates to
@nimbus/codegen — so npx convex codegen works inside a Nimbus app.
Code generation: packages/codegen
Section titled “Code generation: packages/codegen”@nimbus/codegen is the generator invoked by nimbus codegen (and the
convex shim above). For an app it produces two layers of artifacts
(packages/codegen/src/main.mjs):
- Developer-facing, in the function source root’s
_generated/directory:api.ts(typed function references),server.ts(re-export shims for the builders),scheduled_functions.ts, anddataModel.d.ts(types derived from the schema definition). - Server-facing, under
.nimbus/convex/: the function manifest (functions.json),schema.json,http_routes.json,auth.config.json, and the runtime bundlebundle.mjswith itsbundle.sha256— the integrity hash the server checks before every invocation.
How those artifacts flow into a deployment is covered in CLI and codegen.
The admin UI: packages/nimbus-ui
Section titled “The admin UI: packages/nimbus-ui”nimbus-ui is a Vite-built React single-page app. It is not deployed
anywhere — it is compiled into the server binary:
crates/nimbus-assets/src/ui.rsembeds the entirepackages/nimbus-ui/dist/directory into the binary withrust-embed, alongside a small static auth page kept undercrates/nimbus-assets/embedded/ui-auth/.crates/nimbus-assets/build.rsfails the build with an actionable message if the UI feature is enabled butdist/index.htmlhas not been built, so a binary can never silently ship without its UI.crates/nimbus-serverdepends onnimbus-assetswith theuifeature and serves the embedded assets at/uifromcrates/nimbus-server/src/http/ui.rs, falling back to the embeddedindex.htmlfor SPA routes.
Adapter helper packages
Section titled “Adapter helper packages”Three small packages smooth over client setup for the protocol adapters:
@nimbus/firebaseprovides a Firebase-styleinitializeAppsurface (packages/firebase/src/app.ts) and a Firestore client (packages/firebase/src/firestore.ts) speaking the Firestore wire protocol via Connect-Web generated protobuf code.@nimbus/mongodbexports a singlemongoUrihelper that builds a connection string pointed at a Nimbus tenant, for use with the stockmongodbdriver.@nimbus/dynamodbexportsclientConfigandendpointhelpers that configure the stock AWS SDK client against a Nimbus endpoint.
In each case the official driver or SDK does the real work; the helper only points it at Nimbus.
Packages ship inside the binary
Section titled “Packages ship inside the binary”Nimbus packages are not on the public npm registry. They travel inside the server binary and are materialized into each app:
packages/*/dist │ staged with per-file SHA-256 manifest ▼crates/nimbus-assets/embedded/packages/ (rust-embed, version-locked) │ nimbus init / dev / codegen / deploy ▼<app>/.nimbus/packages/<name>/ + .version stamp ▲"convex": "file:./.nimbus/packages/convex" (scaffolded package.json)- A staging script copies each built package — plus three co-provisioned
third-party ESM roots (
@bufbuild/protobuf,@connectrpc/connect,@connectrpc/connect-web) — undercrates/nimbus-assets/embedded/packages/with a checksummedmanifest.json, whichcrates/nimbus-assets/src/js_packages.rsembeds into the binary. crates/nimbus-bin/src/provision.rswrites the embedded payload into<app>/.nimbus/packages/, resolving the dependency closure for the selected adapter, and stamps.nimbus/packages/.versionwith the manifest digest only after every file lands — so an interrupted run is rewritten on the next call.- Scaffolds reference the payload with
file:specifiers (for example"convex": "file:./.nimbus/packages/convex"in the embedded init template), sonpm installresolves entirely offline. - On a binary upgrade the stamp drifts, provisioning rewrites the payload,
and the installed copies are invalidated so Node reinstalls from the
fresh bytes.
nimbus packages verifyre-checks every provisioned file against the embedded checksums.
The codegen tooling itself (a prebundled @nimbus/codegen plus esbuild)
is embedded the same way but is not provisioned into apps — it is
materialized to a temporary directory when the binary runs codegen.
The net effect: the SDK version is a property of the binary, not of a
registry lookup. A given nimbus binary always provisions exactly the
package bytes it was built with, verified by hash.
Where to go next
Section titled “Where to go next”- SDK reference — entry points, classes, and hooks in detail.
- CLI and codegen — how generated artifacts become a deployment.
- Adapters — the server-side protocol surfaces these packages talk to.
- Developers guide — task-oriented guides per surface.