Browser-based AR try-on at 30+ FPS using MediaPipe FaceMesh (468 landmarks) — anatomy-aware anchors, custom landmark smoother, head-rotation compensation, and Shopify Storefront GraphQL integration with deep-linked variants.
About the Project
Virtual Jewelry Try-On is a browser-based AR experience that lets shoppers see how necklaces and earrings look on them in real time — no native app, no paid third-party SDK. It uses MediaPipe FaceMesh to extract 468 3D facial landmarks from a 640×480 webcam feed every frame, then composites jewelry images onto a transparent HTML5 canvas layered above the video using a requestAnimationFrame loop. The catalog is pulled directly from a merchant's Shopify storefront via the Storefront GraphQL API, so inventory and variants are managed in one place and instantly available in the AR experience.
Anatomy-aware placement anchors earrings to ear tragion + earlobe landmarks (indices 234/58 and 454/288) and necklaces to chin landmarks (132, 152, 361), dynamically scaling to the user's neck width. A custom LandmarkSmoother class applies an exponential moving average (smoothing factor 0.8) across frames to eliminate jitter. Head-rotation compensation computes yaw / pitch / roll from nose-tip and outer-eye landmarks so jewelry tracks naturally when the user turns their head. A FacePositionGuide scores how well-centered and properly-sized the face is (0–100) and surfaces feedback like 'Move closer' or 'Move face left' so the try-on always looks ideal.
The SPA is component-driven with two custom hooks (useCamera for MediaStream lifecycle, useFaceTracking for FaceMesh wiring), a domain utilities layer (LANDMARK_INDICES, LandmarkSmoother, FacePositionGuide, getEarPositions, getNecklacePosition, getDynamicNecklacePosition, getHeadRotation, adjustForHeadRotation), and a Shopify data-access layer (typed GraphQL fetch wrapper + product-by-handle, get-all-images, products list). ?handle and ?id query parameters let a Shopify product page deep-link straight into the try-on with the correct variant pre-selected. Cross-origin Image loading (crossOrigin='anonymous') keeps the canvas export-safe when drawing Shopify CDN assets. All face detection and rendering happens entirely on-device — no video frames or landmarks are uploaded.
Key Highlights
Technical Breakdown
Feature areas & implementation details
Related Writeups
Technical posts drawn from this project's real challenges