Case Study · Candela

Candela: from a QR scan to a living candle in one redirect

The full-stack activation platform of the Intelligent Digital Data Assurance System ecosystem: zero-friction QR onboarding, a sensor-driven WebGL candle ritual, and accrue-then-charge enterprise billing, serving two brands from one codebase.

Candela: from a QR scan to a living candle in one redirect

0

Redirect from scan to candle

0fps

Shader flame on mobile

0+

REST endpoints

Challenge

Converting a person standing in a salon, library, or event venue into a tracked, attributable digital participant traditionally requires app installation, registration, email confirmation, and a password, each step shedding a large fraction of participants. Meanwhile the businesses placing those QR codes need the opposite of anonymity: hierarchical roles, attribution of every signup to the exact link and person who generated it, and analytics that survive across devices.

The brief resolved to one question: how do you give an anonymous person a fully functional, attributable account the instant they scan a QR code (before they have told you anything about themselves) while preserving a complete organizational attribution chain for the business that placed the code?

Approach

We inverted the identity model. Accounts exist in three progressively hardened states (temporary, verified, permanent), so an anonymous scanner is authenticated, role-assigned, and attributed in the referral tree before typing a single character. Attribution is structural, not inferred: referral relationships are self-referencing foreign keys, so any member’s full downline is a recursive query.

One Next.js codebase serves two brands through host-based middleware: the Intelligent Digital Data Assurance System B2B platform (distributors, links, batches, analytics) and the Candela consumer PWA, each with its own trust model behind a JWT context discriminator. Scanning a code "ignites" a virtual candle rendered by a hand-written signed-distance-field fragment shader (chosen after a five-way rendering bake-off against Lottie, PixiJS, and Three.js) and controlled by real sensors: microphone RMS for blow-out, accelerometer for shake, gyroscope for tilt.

The hot path never touches React: sensor state and 15 shader uniforms live in refs and GPU memory, updated by two synchronized 60 fps loops. Monetization runs accrue-then-charge on Stripe: usage accumulates against a running balance and is charged only past a threshold, so micro-transactions never hit the card network.

Outcome

The frictionless ideal holds in production: scan to meaningful experience in a single HTTP redirect, with idempotent scan handling, concurrency-safe sealing, and per-candle PWA manifests so each home-screen install deep-links to its own candle.

Both services deploy scale-to-zero on Google Cloud Run, with speculative module preloading and first-paint discipline ensuring cold infrastructure never produces a cold experience: a sustained 60 fps flame on mid-range mobile hardware with near-zero reconciliation cost.

Move the cost off the critical path: accounts before credentials, permissions at the moment of meaning, rendering on the GPU before React hears about it.

Moeez Ahmed · Author, Activation Platform Case Study

Architecture

How the system fits together, straight from the design docs.

two brands · one deployment

iddas.tech

B2B · distributors · links · analytics

candela.app

Consumer PWA · scan · ignite · share

host header

Next.js Middleware

Host-based routing · dual auth realms

reverse proxy /api/*

NestJS Backend

Auth · Links · Candle · Enterprise · Stripe

TypeORM

PostgreSQL 16

Referral trees as FKs · JSONB event ledger

progressive identity

TEMPORARY

auto email · 1h token

verify email

VERIFIED

email link · 24h JWT

set password

PERMANENT

real creds · 7-day tokens

Authenticated, role-assigned & attributed before typing anything.

candle lifecycle

LIT

QR scan · ephemeral

save

SAVED

persistent · installable

seal

SEALED

immutable lineage

anchor

ANCHORED

owned · billed

Sharing at any stage mints a child candle (parentCandleId).

Want results like these?

Tell us what you’re building.

Start a Project

Opening case study

Candela

loading assets0%