Your AR prototype works perfectly in the living room. Ship it to a client site and the virtual monitor drifts three feet left by lunch. The hologram anchored to the conference table? Floating near the ceiling by afternoon. This isn't a tracking bug. It's the fundamental problem of world-locked content without persistent anchors.
Why Drift Happens
WebXR's default reference spaces (local, local-floor, bounded-floor) are relative to the session start pose. The headset builds a map of the room as you move, constantly refining its understanding of where the floor and walls actually are. Every refinement shifts the coordinate system. Your content, parented to that shifting frame, slides along with it.
Plane detection helps you place objects initially, but planes update. A detected floor plane might rise 2cm when the user walks to the far wall. The virtual keyboard on that plane rises with it.
Spatial Anchors Lock Content to Reality
A spatial anchor represents a fixed pose in the real world that the runtime maintains across session resumptions. When you create an anchor at a specific hit-test result, the runtime ties that pose to its internal map of the space. As the map refines, the anchor updates to stay glued to the same physical point.
This works today in stable WebXR on Quest, Vision Pro, Android (ARCore), and iOS (ARKit). No experimental flags required.
Persist Anchors Across Sessions
The anchor UUID is your key to persistence. Store it with your scene data. On next session, request the anchor by UUID before rendering.
Plane Detection + Anchors = Robust Placement
Don't choose one. Use planes for discovery and anchors for commitment.
- Run plane detection to visualize surfaces and guide user placement
- On user confirm, create anchor at the hit-test pose on that plane
- Stop plane detection (saves CPU) and rely on anchor for pose
- If anchor becomes unstable, restart plane detection for re-anchoring
This pattern handles the full lifecycle: discover â place â persist â recover.
| Scenario | Without Anchors | With Anchors |
|---|---|---|
| Session resume | Content floats at origin | Content snaps to physical spot |
| Map refinement (walking) | Drift accumulates | Pose corrected per frame |
| Different room | Content stuck in wrong place | Anchor missing â graceful fallback |
| Multi-device (same space) | Manual alignment needed | Shared anchor UUIDs align instantly |
Common Pitfalls
Creating anchors every frame. Anchors are heavy. Create once per placement action. Reuse the anchorSpace for rendering.
Ignoring trackingState. An anchor can go from 'tracking' to 'unstable' if the runtime loses the map region. Always read it in your render loop.
Assuming anchors survive map clears. User resets guardian? Anchors gone. User switches headset accounts? Anchors gone. Design your fallback UX first.
Over-anchoring. 50 anchors in a room taxes the runtime. Cluster nearby objects under one parent anchor when possible.
"The teams shipping reliable AR in 2026 treat anchors as infrastructure, not features. They build the persistence layer once and every experience inherits stability.
â WebXR Working Group participant
Your Next Steps
1. Add anchor creation to your placement flow this week. 2. Implement UUID storage and restoration. 3. Build the 'anchor lost' recovery UI before you need it. 4. Test across a full day: place at 9am, walk away, resume at 2pm, resume tomorrow.
The difference between a demo and a product is whether the virtual monitor is still on the desk when the client returns from lunch.
âĻ










