Glowup ← Back to the mirror

The guide

How this site
was made.

An honest write-up of the stack, the measurement method and the design decisions behind GLOWUP — specific enough that you could reproduce the approach this weekend.

01 — The stackTwo HTML files, no build step

GLOWUP is a static site: one index.html carrying all markup, CSS and JavaScript inline, plus this guide page. No framework, no bundler, no external dependencies at all — even the three typefaces are self-hosted woff2 files. It deploys to Cloudflare Pages by dragging a folder into the dashboard.

02 — The measurementSkin, read in CIELAB

The diagnostic converts skin pixels from sRGB to CIELAB, the color space used in dermatology, because distances there roughly match how humans perceive color difference. Two angles do the diagnostic work:

// Depth — the Individual Typology Angle (ITA°),
// dermatology's standard for skin lightness:
ita = atan2(L − 50, b) · 180/π
// fair > 55° · light > 41° · medium > 28° · tan > 10° · deep ≤ 10°

// Undertone — the hue angle in the a/b plane:
hue = atan2(b, a) · 180/π
// warm ≥ 54° · neutral 46–54° · cool ≤ 46°

Before measuring, pixels are filtered with a coarse skin-mask (red dominant over green over blue, enough chroma, enough warmth) so hair, background and clothing don't skew the average. The center crop of the photo (25–75% wide, 18–72% tall) biases sampling toward the face. Depth × undertone then indexes into a 9-season matrix — the classic seasonal color system — and into a Shade iD: the foundation family expressed in shopping language like "golden honey · caramel".

Honest limits: a phone photo is not a spectrophotometer. White balance, indoor lighting and filters shift the reading — which is why the mirror asks for daylight and bare skin, and why results are framed as a family, not a single shade.

03 — The designEditorial warmth, lab precision

The visual language plays two registers against each other: a beauty-editorial voice and an instrument-panel voice, because the product itself is "taste, measured".

04 — The assetsOne image, by budget

The performance budget came first: ≤ 1.5 MB total, LCP under 2 seconds on 4G. Exactly one raster asset earned its place: the editorial portrait inside the mirror, generated with Higgsfield's Soul model on a prompt written for the site's palette, then resized and compressed to a 24 KB WebP. Everything else is CSS gradients or inline SVG — the seal, the favicon, the grain — and the fonts are self-hosted woff2, so the whole page ships in roughly 250 KB with zero third-party requests.

The product edit is data, not images: a JSON catalog with a clean search term (q) per product and a per-retailer urls override, designed to be refreshed by an Apify scrape with exact product URLs. Until an override exists, links fall back to each retailer's public search on the clean term — never broken, never brand-paid.

05 — Reproduce itThe checklist

← Try the diagnostic