Lluminor
FrontendLive

Bevel

A specification becomes matter — 16 SKUs that can't contradict themselves.

PersonalWebE-Commerce2026 – present

Overview

A concept storefront for a fictional maker of precision desk instruments — machined rules, dividers, marking knives, desk objects. Every object exists in two states: the parametric technical drawing that specifies it, and the machined thing that results, and the product page cross-fades between them on a keypress. Nothing in the catalogue is hand-stated: mass is derived from bounding volume × a solidity factor × the metal's real density, prices roll up from variant factors, and a build-time validator rejects any of the 16 SKUs that contradict itself. Deployed as Cloudflare Workers static assets with no Worker script at all — there is no API, no payment field, and the order lives in one localStorage key.

Bevel is a portfolio piece built as the storefront of an instrument maker that does not exist. The premise drives the whole interface: a specification becoming matter. The UI is drawn in the language of a technical drawing — hairlines, dimension lines carrying real millimetres, a 45° chamfer on every panel — and the palette enforces the split, with an analogous cool run (teal → cyan-blue → blue) reserved for structure and a warm brass-to-rust complement reserved for matter and every interactive state. Cool never signals interactivity; warm never draws structure.

Nothing derivable is written down. src/data/derive.ts computes mass as bounding volume × volumeFactor × the material's real density, so changing a thickness moves the weight — the 150 mm steel rule lands at 44 g, which is what a real one weighs. Kits recurse into their components for both volume and price. Twelve of the sixteen objects render as parametric SVG drawings generated from their own proportions across nine profiles, all drawn at one shared scale so a 100 mm rule reallyphishing page with good taste.

The claims the project makes are machine-checked rather than remembered: verify:catalog asserts catalogue invariants (unique slugs, variants only in materials the maker offers, plausible derived mass, resolvable kit components, sets cheaper than their parts), verify:lazy asserts three.js is genuinely deferred and degrades, verify:order walks the order flow and asserts no card fields exist, and verify:a11y measures contrast, accessible names, focus and heading order in-page via Puppeteer. Hosting is Cloudflare Workers static assets with no Worker script: security headers ship from public/_headers because the asset layer serves files directly and never invokes a Worker decorating env.ASSETS.fetch() on a normal page load. Fonts are excluded from Vite's inline limit so font-src can stay 'self'.

Stack

UI / Frontend

TypeScriptReactViteTailwind v4Zustand

Animation / 3D

Three.jsReact Three Drei

Infra / Deploy

Cloudflare Workers

Tooling / AI

ESLint

How it works

01

Catalogue

Sixteen SKUs rendered as parametric drawings at one shared physical scale, filterable by material, kind and finish.

02

Product page

Spec table assembled in one place from derived values — dimensions, computed mass, tolerance — beside the object viewer.

03

Object ↔ drawing

Press D or the button and the machined thing cross-fades into its drawing in the same frame at the same size; three.js loads lazily on approach, or never for reduced-motion and WebGL failures.

04

Order

Lines added to a Zustand store persisted to one localStorage key, re-validated against the live catalogue on rehydrate so stale slugs and retired variants are dropped rather than rendered as holes.

05

Checkout

Three steps — Details, Method, Review — with real field validation and the step held in the URL so a refresh keeps progress. No payment field exists.

06

Deliberate refusal

The order is confirmed locally, the store is cleared, and nothing is ever sent anywhere: there is no server, no API, and no charge.

More projects

Jamil Harun · 2026