ReactVision Spatial, the services that
make a place persistent and shareable

The spatial services layer behind ViroReact. Cloud anchors, room-scale scans, geospatial anchors, a live co-location channel, and replicated application state, written in C++ with no external vision libraries and no Google dependencies. It ships inside the ViroCore engine, so there is nothing to install on its own.

01Shipping
Cloud anchors

Host a spot and relocalise it across devices and sessions, from camera imagery and the AR point cloud. Persistent, shared AR content in one place.

02Shipping
Room-scale scans

Walk a room and host it as an anchor that carries its own coordinate frame, with no tapped anchor to be relative to. The VPS half of the library.

03Shipping
Geospatial anchors

Anchors placed at latitude, longitude, and altitude, and the maths that projects GPS into the AR frame.

04Shipping
Co-location channel

Live peer poses between devices that share a frame, at 20 Hz. Lossy by design: the next pose supersedes the last.

05Shipping
Replicated state

Ordered, conflict-resolved, server-authoritative application state for those devices. Saved when a room empties and reloaded when it reopens.

v1.2.0, proprietary, shipping inside ViroReact. Five independent subsystems: an app can use one and ignore the rest.


What Spatial is

ReactVision Spatial is the spatial services layer behind ViroReact: everything that makes a place persistent and shareable between devices. It provides cloud anchors, room-scale scans, geospatial anchors, a co-location channel, and replicated application state, written in C++ with no external vision libraries and no Google dependencies, and it reaches apps through the ViroCore engine as a prebuilt library.

Nothing here is called directly from an application. The API an app sees is on ViroReact's ViroARSceneNavigator, and this library sits behind it: host and resolve a cloud anchor, start and finish a scan, create and find geospatial anchors, join a co-location room. Both live channels are served by ReactVision's hosted relay, so an app passes an API key and a project id and nothing else.

Spatial is proprietary, unlike the rest of the ReactVision stack. The renderer that exposes it, ViroReact, stays MIT licensed, and the code an app writes is the open ViroReact API. Co-location requires a paid Studio plan.

How a cloud anchor is hosted and resolved

Two halves. Hosting turns what a device saw into a compact, relocalisable description of a spot. Resolving finds that spot again from a different device, in a different session, with a different world origin.

Host
01

Collect keyframes continuously

From the moment a provider exists, camera frames are captured into a ring buffer on a background thread. A frame is kept only when the camera has moved at least 2 cm or turned 5 degrees, so the buffer holds distinct viewpoints rather than duplicates.

02

Describe each frame

Each keyframe is subsampled, equalised for lighting, and run through ReactVision's own SIFT implementation: a difference-of-Gaussians pyramid and 128-byte descriptors, up to 1,000 keypoints per frame on the host side.

03

Triangulate and upload

On host, keyframe pairs with enough baseline are matched and triangulated into anchor-local 3D points, deduplicated on a 2 cm grid, gated for quality, then serialised into ReactVision's binary anchor format and uploaded to the platform.

Resolve
01

Match the live frame

The current camera image is described the same way and matched against the stored descriptors. The heavy work runs on a detached background thread so the render loop stays smooth.

02

Solve the pose

P3P RANSAC estimates the camera pose from the 2D to 3D matches, a descriptor-quality gate rejects geometrically lucky but wrong matches, and Gauss-Newton refinement tightens the result. Scan-built anchors are refined over yaw and translation only, because their frame is gravity-aligned by construction.

03

Vote before accepting

A pose is accepted when three of the last ten solves agree within 45 cm. The reported pose is the cluster member with the most inliers, so one outlier between two good solves no longer stalls a resolve.

The result is a transform from the anchor's local frame into the current device's world, which is what lets content placed by one person appear in the same place for the next.

Room-scale scans and the coverage gate

A scan is a cloud anchor without a tapped anchor to be relative to. Walk the room, and the library computes a location frame from the scan's own geometry: origin at the centroid of the triangulated points, orientation yaw-only against gravity. Content placed against a scan travels in that frame, never in world coordinates.

MeasureMinimum
Triangulated points40
Spread of those points1.0 m
Viewpoint pairs at least 3 cm apart5

A scan reports its own progress while it happens. An app can poll the keyframe count, camera spread, and usable viewpoint pairs, each beside the threshold it is judged against, so a rejected scan can say which number was short. These thresholds were set for device bring-up and will be tuned from measured scans.

Co-location and replicated state

A resolved anchor gives every device in a space the same origin. Two channels carry what they say to each other about it, on two sockets, because poses and application state cannot share one set of rules.

Co-location channel

Where each peer is, at 20 Hz

Frame-native data only. Poses originate in C++ at frame rate and never cross the JavaScript bridge. The channel is lossy by design: the next pose supersedes the last, so nothing is queued and nothing needs replaying.

Room
The cloud anchor id. Peers that resolved the same anchor share a room; there is no separate session concept.
Coordinates
Always the anchor's location frame, never world coordinates. Each AR session starts its world wherever tracking began, so a world pose means nothing to another device.
Rate
Poses go out at 20 Hz and receivers interpolate. A pose inside the interval is dropped, not queued, so there is no backlog after a reconnect.
Reconnection
Automatic, with capped backoff. Losing the socket loses the peers for a moment, never the frame.
Replicated state

What the room agrees on

Application state originates in JavaScript and must not be lossy, so it is server-authoritative and totally ordered. A server already sits in the path, and only a server can express a refusal, which ownership requires. State is saved when a room empties and reloaded when it reopens.

Authority
Clients propose operations; the server accepts or rejects each one, assigns the room's next sequence number, and broadcasts. Ordering is identical for everyone.
Ownership
Ownership gates mutation, so the peer dragging an object is the only one that can move it.
Concurrency
An expected version opts into optimistic concurrency, with the current value returned on refusal. Unowned entities are last-writer-wins.
Departure
A peer that leaves releases everything it held, so a crash mid-drag does not lock an object for the life of the room.

Platform support

The anchor pipeline needs ARKit or ARCore camera frames. The two live channels need only a network socket, which is why they reach further than the pipeline does.

PlatformCoverage
AndroidEverything.
iOSEverything.
visionOSChannel and replication only. The AR pipeline needs camera frames, which visionOS grants only under an enterprise entitlement.
Meta QuestNot a target for this library. Quest co-location uses Meta's own spatial anchors, inside ViroCore.

There is no desktop build: a host has no camera frames, and the build says so rather than producing something that cannot work.

Why we built our own

Most AR stacks lease their anchors from a platform vendor. ReactVision owns this layer for the same reason it owns the engine: so one codebase reaches every device, and so the whole stack can run where the customer needs it.

Our own vision pipeline

Feature detection, description, triangulation, and pose estimation are ReactVision code. There is no OpenCV, no Google Cloud Anchors service, and no third-party SLAM library in the path.

Our own formats and transport

Anchors are stored in a compact binary format the library reads and writes itself, and networking uses the platform's native HTTP and WebSocket stacks. No libcurl, no extra runtime.

One engine, one API key

Nothing is installed on its own. The library ships inside ViroCore, ViroReact exposes it on ViroARSceneNavigator, and an app passes an API key and a project id. Keys never appear in the JavaScript bundle.

A path to running it yourself

The repository carries a reference server for the co-location and replication endpoints, written to run locally or as an edge function. It is the starting point for the on-premises deployments on the enterprise and defence pages.

This is the infrastructure that the Defence page and Enterprise page describe deploying on a customer's own servers.

Status

Version
v1.2.0

Released 19 September 2026. First release, v1.0.0, in January 2026.

Licence
Proprietary

The one closed-source layer of the stack. Exposed through the MIT-licensed ViroReact API.

Reaches apps
ViroCore

As a prebuilt library inside the engine. Nothing to install; add an API key and project id.

Frequently asked questions

What is ReactVision Spatial?
ReactVision Spatial is the spatial services layer behind ViroReact: everything that makes a place persistent and shareable between devices. It provides cloud anchors, room-scale scans, geospatial anchors, a co-location channel, and replicated application state, written in C++ with no external vision libraries and no Google dependencies, and it reaches apps through the ViroCore engine as a prebuilt library.
Is ReactVision Spatial open source?
No. Unlike the rest of the ReactVision stack, Spatial is proprietary. The ViroReact renderer that exposes it remains MIT licensed, and the API an app calls is the open ViroReact API on ViroARSceneNavigator.
How do I use Spatial in my app?
You do not install it directly. It ships inside the ViroCore engine that ViroReact uses, and ViroReact exposes it through ViroARSceneNavigator: hostCloudAnchor, resolveCloudAnchor, startScan, finishScan, and the geospatial anchor methods. Add an rvApiKey and rvProjectId from your ReactVision Studio account and the library handles the rest.
Does Spatial depend on Google or any third-party vision library?
No. Cloud anchors, scans, and geospatial anchors are ReactVision's own C++ implementation with no OpenCV, no Google Cloud Anchors service, and no external SLAM library. Networking uses the platform's native HTTP and WebSocket stacks.
Which platforms does Spatial support?
Everything on Android (API 24 and above, ARCore 1.51 and above) and iOS (15 and above, ARKit 3 and above). On visionOS, only the co-location channel and replicated state build, because the AR pipeline needs camera frames that visionOS grants only under an enterprise entitlement. Meta Quest is not a target for this library; Quest co-location uses Meta's own spatial anchors inside ViroCore.
What is the difference between the co-location channel and replicated state?
The channel relays peer poses and is lossy by design, since the next pose supersedes the last a few milliseconds later. Replicated state carries application state that cannot work that way, so it is server-authoritative and totally ordered, with ownership and conflict rules, and it is saved when a room empties and reloaded when it reopens.
Can Spatial run on our own servers?
The repository includes a reference implementation of the co-location and replication endpoints, written to run locally or as an edge function, as the starting point for self-hosting. For a supported on-premises deployment of the full platform, including anchors and asset hosting, talk to the enterprise team.

Build on Spatial through ViroReact

Cloud Anchors and Geospatial Anchors are documented from the app's side in the ViroReact docs. For co-location, self-hosting, or an on-premises deployment, talk to the team.