Neonvil Logo
Budget Calculator
Neonvil Logo

contact@neonvil.com

© 2026 Neonvil Inc.


Budget Calculator
Back to Case Studies
FEATURED INSIGHT
A diamond that remembers. Every stone we sell now carries its own story — photos, videos, the moments that made it personal — and our buyers unlock it all just by scanning the stone itself. No accounts, no passwords, no friction between the physical object and the memory it holds.

NEONVIL & Confidential Luxury Client

A Case Study: A Zero-Trust Media Time Capsule Unlocked by the Diamond Itself

Business Outcome

A live, production-deployed mobile SPA that turns a physical diamond into a private, credentialless media time capsule — photos, videos, and journal entries bound to the stone, unlocked by scanning the QR on its certificate.

Credentialless Access

The QR on the diamond is the only key — no accounts, no passwords, no email. The physical object is the login.

Private by Default

Every photo and video stays private. Access is granted only while the owner is actively using the capsule, and expires on its own — nothing lives behind a permanent link.

Safe by Every Release

Every release ships the app and its security guarantees together — there is no window where new features run against stale rules.

Context & Challenges

Every diamond the brand sells is physically unique, but once it leaves the boutique there's no digital tether between the stone and the owner's story. The client wanted a time capsule the buyer unlocks by scanning the diamond's QR code — turning a one-off purchase into an ongoing emotional artefact (photos, videos, journal entries bound to the stone), with no accounts, no passwords, and no permanent URLs.

Four critical engineering challenges:

01

Credentialless, shareable access tied to a physical object: 32-byte session token minted on scan, 1-hour Firestore TTL, scheduled pub/sub purge — client never touches Firestore or Storage directly.

02

Private media without public URLs: signed URLs regenerated server-side on every read, with cross-verified qrCode metadata on delete — no permanent download tokens to leak.

03

Multipart ingestion on serverless with no Express middleware: Busboy streaming parser with MIME whitelist, 50 MB/file cap, 10-file batch limit, bumped memory and timeout on the upload function only.

04

Workshop chain-scanning with stale state: URL-vs-store mismatch detection plus a hard remount forces vendor iframes (Kiradam v360) to re-initialise cleanly between stones.

Project Goals

Mobile SPA

A React 19 + Vite app with a native-camera QR scanner, in-app photo/video capture, lazy media gallery, fullscreen viewer, and a story journal.

Cloud Functions Backend

A Node 20 Gen 2 function set for product, media, story, and scheduled cleanup — with Busboy streaming uploads and signed-URL delivery.

Zero-Trust Infra

Deny-all Firestore and Storage rules, per-IP rate limiting, and a GitHub Actions pipeline that deploys code and rules atomically.

Our Solution

Three layers with distinct responsibilities. The mobile SPA owns camera, scanner, and capture. The Cloud Functions backend mediates every read and write, issues ephemeral sessions and signed URLs. The rules-and-pipeline layer makes the zero-trust posture the default state, not a deployment checklist.

Mobile SPA

Native-camera QR scanning via getUserMedia + jsQR frame parsing

Diamond certificate view with embedded Kiradam v360 video

In-app photo/video capture and file-picker upload with progress

Lazy media gallery with fullscreen viewer and story journal drawer

Cloud Functions Backend

Busboy multipart parsing with MIME whitelist and size enforcement

Session tokens minted on scan, verified on every write call

Signed-URL generation for every media read, metadata-verified deletes

Scheduled pub/sub cleanup of expired sessions and per-IP rate limiting

Zero-Trust Infra

Deny-all Firestore and Storage rules — 100% of traffic flows through functions

Service accounts and secrets managed through GitHub Actions

Atomic deploys of hosting, functions, and rules on merge to main

PR preview channels for safe UX iteration on live data contracts

Effort Allocation

100%

Frontend UI/UX & Polish (30%)

Security & Hardening (20%)

Backend / Business Logic (20%)

Infrastructure & CI/CD (10%)

Integrations (10%)

Requirements & Spec (10%)

Infrastructure & Technologies

FRONTEND

React 19 + Vite

Chosen for a mobile-first SPA with sub-second cold boot on 4G — Vite HMR kept iteration fast through many UX polish cycles, and React 19 handled the camera-driven scanner UI without blocking the main thread.

STATE
🐻

Zustand (persist)

Chosen for cross-route state that survives page reloads without Redux boilerplate, and to cleanly swap product on chain-scan without prop-drilling through the scanner, gallery, and journal views.

INTEGRATION
📷

jsQR

Chosen to decode QR codes from live canvas frames in pure JavaScript — avoided a native-app dependency, one camera permission, works on iOS Safari and Android Chrome.

BACKEND
🟧

Firebase Cloud Functions Gen 2

Chosen for pay-per-invocation scaling with no servers to patch — the v2 API also fixed CORS issues the v1 onCall had in this setup, while giving us streaming request bodies for multipart uploads.

INGESTION
📦

Busboy

Chosen as the only practical multipart parser for Cloud Functions Gen 2 streams — enabled per-file MIME validation and size enforcement before bytes ever reached Storage.

SESSION
🔥

Firestore + Scheduled Pub/Sub

Chosen to hold short-lived session tokens with TTL semantics — a 60-minute cron function purges expired rows, replacing a Redis TTL cache with zero extra infrastructure.

STORAGE
🔐

Signed URLs (Admin SDK)

Chosen to deliver private-by-default media with time-boxed access — no permanent download tokens to leak, and revocation is implicit (just stop reissuing).

INFRASTRUCTURE
⚙️

GitHub Actions + firebase-tools

Chosen so hosting, functions, Firestore rules, and Storage rules deploy atomically — preventing the classic "new code, old rules" security gap on every release.

Back to Case Studies