Build guide · Generative Assets

How Trueline Glass & Glazing was made

The concept. Trueline Glass & Glazing is a fictional Osborne Park glazier — cricket-ball windows, 7am break-in board-ups, shower screens and compliance-letter safety upgrades across Perth's inner north. The page has one job: book a same-day measure. The art direction is the glass rack in morning showroom light — clean panes leaning in the A-frame, the green glow float glass only shows on its edge — precise and unhurried, zero cracked-glass drama.

Palette — argued from the racked pane

#F5F7F6 daylightground — morning light through clean glass
#2B3134 frame charcoalstructure & primary ink — powder-coated frames
#3E8E7E glass-edge greenLINE/MARK only — cut lines, dimension marks, edge glow
#256B5D edge-inkderived — small green text on daylight, 6.3:1
#2F7566 deep bevelderived — CTA fill under white text, 5.4:1
#8C979D silicone greythe neat bead — borders and hairlines, never text

The spec's ink/line rule applied twice: glass-edge green fails 4.5:1 as small text on daylight (3.9:1), so body-scale green is set in the derived #256B5D and buttons in #2F7566; the bright #3E8E7E is reserved for lines, marks and the pane's edge glow. Silicone grey measures 2.75:1 and is confined to borders.

Type

The signature — Pane Estimator

Job chips (window re-glaze / shower screen / splashback / sliding door), glass chips (4 mm float / toughened / laminated / obscure) and 300–2400 mm width/height steppers drive a procedural SVG pane drawn face-on and edge-on. Geometry is laid out in JS at 0.125 px/mm and eased to new dimensions with a 240 ms cubic-out requestAnimationFrame lerp (instant under reduced motion). The glass type renders procedurally: float's reflection streak lives in a clipPath that tracks the pane rect; toughened gains the etched corner stamp "T — AS 1288"; laminated thickens the edge-on bar and draws the interlayer seam; obscure overlays an SVG <pattern> frost. Scene swaps (shower screen, splashback) toggle SVG groups via the hidden attribute — with the [hidden]{display:none!important} guard, and never g.hidden=true, which silently no-ops on SVG. The live state (job, glass, dims, billed area, price, form status) is exposed at window.__glazier for QA.

Pricing model — shape, anchors, derivation

Model: price = fit fee + glass rate × billed area, where billed area = max(actual m², 0.5 m² minimum billable pane). The minimum is the derivation that makes every pinned "from" anchor exact: $120 + rate × 0.5 reproduces $190 float, $280 toughened, $260 laminated, $220 obscure.

ComponentValueSource
Fit & seal fee (window)$120pinned
Fit fee (sliding door, incl. new rollers + track service)$180derived — $180 + $320 × 0.5 = the pinned $340 floor
4 mm float$140/m²pinned
Toughened 6 mm$320/m²pinned
Laminated 6.38 mm$280/m²pinned
Obscure 4 mm$200/m²pinned
Sliding-door floor$340pinned — laminated sliders would otherwise undercut it, so the floor applies

Rounding rule: the glass line rounds to the nearest dollar (Math.round(rate × billed)) and the total is fee + rounded glass line, so the card never argues with its own line items. The oracle in QA keeps exact arithmetic. Measured rest example: 1200 × 900 mm toughened window = 1.08 m² → $120 + round($345.60) = $466, matching the spec's cross-derived ≈$466. Cheapest reachable output — float window at minimum size — measures $190, equal to the services grid's re-glaze floor.

Honest disables (no control computes a dishonest figure): shower screens and splashbacks are quoted-on-measure scopes — selecting them disables the steppers and glass chips with the reason on-page ("screens are priced by configuration, not area — the measure is free") and the card shows only the pinned anchors ($680 / $1,250 semi-frameless / frameless; $420/m² splashbacks). Sliding doors disable float ("can't legally go in a door under AS 1288") and obscure ("comes as toughened obscure, quoted with the pattern in hand"), auto-switching to toughened with the switch announced. The pane-weight second read uses flat glass mass at 2.5 kg/m² per mm of thickness.

Conversion decisions

Local SEO we'd implement for the real business

This demo deliberately ships only WebPage schema naming it a demonstration — fictional LocalBusiness/Review data in a real index is dishonest markup. For a real Trueline, we'd ship:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "Trueline Glass & Glazing",
  "description": "Window re-glazing, shower screens, splashbacks
    and emergency board-ups across Osborne Park and Perth's
    inner north. Installs to AS 1288 & AS 2047.",
  "telephone": "+61-8-XXXX-XXXX",
  "address": { "@type": "PostalAddress",
    "addressLocality": "Osborne Park", "addressRegion": "WA",
    "postalCode": "6017", "addressCountry": "AU" },
  "areaServed": ["Osborne Park","Tuart Hill","Yokine","Balcatta",
    "Stirling","Innaloo","Karrinyup","Dianella","Mount Hawthorn",
    "North Perth","Leederville","Wembley"],
  "openingHours": ["Mo-Fr 07:00-17:00","Sa 08:00-12:00"],
  "priceRange": "$$",
  "review": { "@type": "Review",
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "author": { "@type": "Person", "name": "[verified customer]" },
    "reviewBody": "[pulled from the live Google / Podium feed]" },
  "aggregateRating": { "@type": "AggregateRating",
    "ratingValue": "[live]", "reviewCount": "[live]" }
}
</script>

Plus suburb-level service pages (the FAQ answers above are each a query cluster: "safety glass requirements WA", "window cracked by itself", "shower screen cost Perth"), Google Business Profile with the board-up line as the primary category action, and review schema fed from a real review platform — never hand-typed.

What would change for the real client

Iteration log

Pass 1 — Craft. Drove the full page headlessly (46 asserts) and read the screenshots. The rendered image caught what the asserts couldn't: the wordmark's "LINE" was rendering at 0.56rem — the sub-brand rule .wordmark span also matched the two-tone span inside the <b>; scoped it to a direct child. The hero A-frame read as a giant letter "A" with panes floating beside it and four etch labels colliding at the base; rebuilt the composition — end-frame plus perspective rail, all panes on a consistent −10° lean with staggered feet, etch labels cut to two. The hero eyebrow orphan-wrapped "PARK" at 375px; shortened to "Glaziers · Osborne Park". Rest card verified at $466 against the independent oracle.

Pass 2 — Depth. Drove every scenario against a reimplemented oracle: float window at minimum size $190 (equals the services floor), slider auto-switching float→toughened at the $340 floor with the AS 1288 reason on-page, laminated slider floored ($320 raw → $340), obscure 2400×1200 at $696, stepper clamps at 2400. Added the price-tick micro-interaction (the total bumps 5.5% with a brief mint flash on change, killed under reduced motion) and kept the second reads: the pane-weight line ("≈ 16 kg — a careful two-hand carry"), and the front rack pane etched 1200 × 900 · 6 T — the estimator's own rest state. Chased a screenshot suspicion that the stepper labels rendered salmon; computed style measured the correct #59646B — an image-scaling artifact, logged rather than "fixed".

Pass 3 — Hardening. Masthead first at 375 per the W18 rule: wordmark and 44px call pill both inside the viewport, no overflow (scrollWidth 375). Empty submit on a fresh load raises all three validation errors with focus moved to the first invalid field; filled submit renders the "Thanks — request received" confirmation with the demo disclosure. Keyboard drive: Enter on a focused chip switches the job. Reduced-motion load settles instantly with the estimator readable at $466. External requests measured as Google Fonts only; every (08) 9xxx number on the page uses the reserved 9000 exchange; JSON-LD live blocks carry WebPage only. Chanel rule: removed the pane's second reflection streak — one is a reflection, two were decoration.