Irvan Fahlepi
Let’s talk

04 — Behind the build

The Lab

The part of campaign work clients don’t see until something breaks: what gets measured, what gets tested and how it ships. The numbers below are live from the three demos.

Live analytics

First-party, cookieless counters, recorded only for visitors who accepted analytics. GA4 receives the same events when it’s configured. Refreshes every 15 seconds.

—Survey answers
—Games played
—Scores submitted
—Story completion
Maison Lumière survey
Started0
Completed0
Shared0
Shade Match game
Played0
Finished0
Submitted score0
Atelier Nº 7 story
Started scrolling0
Reached the end0
Survey results by fragrance family
Floral0
Woody0
Citrus0
Amber0
Shade Match leaderboard

    Lighthouse

    Every page, measured on the production site on 2026-11-05 with Lighthouse 12 (best of three runs each). Mobile is Lighthouse’s simulated mid-range phone on slow 4G, the harshest of its settings.

    Index/

    Desktop
    100Performance
    100Accessibility
    100Best practices
    100SEO
    Mobile
    100Performance
    100Accessibility
    100Best practices
    100SEO

    Shade Match/loreal-shade-match

    Desktop
    100Performance
    100Accessibility
    100Best practices
    100SEO
    Mobile
    100Performance
    100Accessibility
    100Best practices
    100SEO

    Maison Lumière/maison-lumiere

    Desktop
    100Performance
    100Accessibility
    100Best practices
    100SEO
    Mobile
    100Performance
    100Accessibility
    100Best practices
    100SEO

    Atelier Nº 7/atelier

    Desktop
    100Performance
    100Accessibility
    100Best practices
    100SEO
    Mobile
    100Performance
    100Accessibility
    100Best practices
    100SEO

    The Lab/lab

    Desktop
    100Performance
    100Accessibility
    100Best practices
    100SEO
    Mobile
    100Performance
    100Accessibility
    100Best practices
    100SEO

    Quality assurance

    Playwright runs every suite on three device profiles for every push. A red cell blocks the merge.

    SuiteDesktop ChromeAndroid · Pixel 7iOS Safari · iPhone 14
    Survey flowAnswers lead to the right fragrance, ties resolve, live distribution renders✓ Runs✓ Runs✓ Runs
    ConsentNo event or Google script before opt-in; choice persists across reloads✓ Runs✓ Runs✓ Runs
    Share cardCanvas renders and downloads a 1080×1350 PNG✓ Runs✓ RunsNot applicable
    Shade MatchFull game with real taps, misses freeze, score reaches the leaderboard✓ Runs✓ Runs✓ Runs
    Scroll storyPage renders end to end and fires start and complete events✓ Runs✓ Runs✓ Runs
    API & anti-cheatEarly, forged, replayed and impossible submissions are rejected✓ RunsNot applicableNot applicable

    Lightweight by design

    Each demo ships only what it needs. Fonts load per page, and motion uses CSS wherever CSS can do it.

    • 0 kBAnimation library on the scroll story. It runs on CSS scroll timelines.
    • AVIFEvery photo is resized and re-encoded by the CDN to the exact size it is shown at, and lazy-loaded below the fold.
    • 145 kBTotal compressed JavaScript for Shade Match, React and the WebGL swatch included.
    • 0 cookiesUntil a visitor accepts. Google’s script isn’t even requested before then.

    How it ships

    GitHub Actions for checks, Vercel for previews and production, Upstash Redis for leaderboards and counts.

    1. 01PushEvery branch
    2. 02CITypecheck · build · Playwright × 3 devices
    3. 03PreviewUnique Vercel URL for client review
    4. 04MergeOnly when checks pass
    5. 05ProductionInstant rollback to any build

    Scores you can trust

    Campaign leaderboards attract cheaters within hours. Shade Match defends itself on the server.

    • Rounds are generated from a seed inside a signed token, so the server can rebuild the exact game it dealt.
    • The score is recomputed from the raw picks. The client never sends a score.
    • The server’s clock decides whether the game lasted long enough. Each token can be used once.
    • Pick counts beyond human reaction time are rejected, and every endpoint is rate-limited per address.