Generative Assets · Industry demo 326 · Carpenter

How Jarrahline was built

A fictional Osborne Park carpentry and decking business, designed and built by Sapience Analytics as a conversion-first landing page demonstration. One job: a deck enquiry with size, timber and price already settled before the phone rings.

The concept

Jarrahline Carpentry & Decking sells decks the way a carpenter builds one: from the tape measure outwards. The signature Deck Planner draws a top-down deck board by board — joists showing through the gaps, grain strokes per board, a drawn tape measure with live dimension callouts — and prices it against pinned WA-market rates as you resize it. The estimate lives on the boards themselves, then walks itself into the quote form. Everything on the page is procedural SVG and CSS; there isn't a raster pixel anywhere.

Palette — argued from the timber rack

Contrast figures below are measured with real WCAG arithmetic from the shipped tokens (Pass 1), not estimated.

#F2EFE9 sanded ashpage ground — a planed, waxed board
#26211B spar charcoalbody ink — 13.9:1 on ash
#7A3122 jarrah heartCTAs & links — 8.0:1 on ash, white on it 9.2:1
#C89B5A pine shavinglines & marks only — tape, rules, grain
#6E5220 shaving-inkaccent-coloured small copy — 6.3:1 on ash
#5A5246 muted inksecondary copy — 6.7:1 on ash

The spec's hypotheses (≈13, ≈8, ≈7, ≈6.5) measured 13.9, 9.2, 8.0 and 6.3 — the jarrah accent is deep enough that no W33 two-token remedy was needed; pine shaving never carries text, only linework, per the standing ink/line split.

Type

Zilla Slab 600 for display — a slab serif with a joinery squareness to it; the bracketed slabs read like dressed timber ends. It carries the wordmark, the section heads, the dimension callouts on the drawing, and the display moment: the deck's area set huge in words ("TWELVE SQUARE METRES, LAID STRAIGHT") that re-sets itself as the steppers move — "TWELVE AND A HALF…" arrives with the next half-metre. Public Sans does the workhorse body: legible, plain-spoken, nothing showroom about it.

Techniques — the Deck Planner

The planner is one hand-built SVG redrawn from state. Each redraw computes the deck rectangle at 58 px/m, lays an under-structure (dark base plus joist bands every 450 mm that show through the 2.5 px board gaps), then generates boards: count derived from the drawn width, each board's fill varied in lightness by a seeded pseudo-random (deterministic per board index, so redraws are stable), with one or two long cubic-Bézier grain strokes and occasional knots — composite gets a single flat stroke and near-uniform boards, which is honest to the material. Balustrade posts and twin stainless-wire runs walk a clockwise offset path around the deck edges to the stepper's length; the demolition toggle draws the old deck's boards lifting away at a corner in dashed jarrah ghosts. A decking-oil sheen — a skewed gradient band clipped to the deck — sweeps on a 7 s rAF loop with the delta clamped at zero and capped (W29), paused when the tab hides, and parked mid-deck under reduced motion, so the signature is visibly alive at any capture instant.

Redraws are dual-speed (W21): the first draw staggers boards in at 26 ms each (capped 1.5 s) as entrance choreography; every later change redraws at 8 ms per board (capped 450 ms) via a firstDraw flag, so stepper taps feel snappy, not laggy. Every control handler bumps a token and resets the settle timer before touching state (W25); the sheen loop reads a live deckRect object rather than closing over rebuilt geometry, so rapid-fire control bursts can't strand a stale animation. The page exposes window.__carpenter — scenario, computed figures and a settled flag — so QA gates on state, never on seconds.

The pricing model — pinned and honest

LineRateRules
Decking, supply + install$340/m² pine · $480/m² composite · $560/m² jarrahMinimum billed area 6 m², billed at the selected timber's rate. At exactly 6.00 m² the minimum binds silently (no note); below it the "billed at the 6 m² minimum" note shows.
Balustrade$290/lm, 0–12 lm × 0.5Kwila posts + stainless wire. Flat over any timber — stated on-card. 0 lm is the designed rest cell: draws nothing, adds $0.
Old-deck demolition+$48/m²Bills the drawn area, not the clamped billing area — the 6 m² minimum applies to the decking line only. Resizing the deck re-prices this line with it (derived-state repricing).
Framing-only, pergolas, built-insNo estimator number by design — quoted from drawings; services-grid ranges only.

Derivation notes

  • Every area is a multiple of 0.25 m² (0.5 m steppers), and 0.25 × {340, 480, 560} = {85, 120, 140} — all totals are whole dollars by construction. Displayed totals are whole-dollar (W26).
  • Worked figures, all measured from the running page: rest 4.0 × 3.0 m pine = $4,080; composite $5,760; jarrah $6,720; rest + 4 lm balustrade $5,240; 5.0 m² pine bills the minimum at $2,040 (with note), 6.0 m² also $2,040 (no note — boundary reachable exactly at 2.0 × 3.0); rest + demolition $4,656; demolition at 15 m² re-prices to $5,820.
  • The estimator's cheapest output — the 6 m²-minimum pine deck at $2,040 — equals the services grid's "new decks from $2,040" floor (W12 consistency contract).
  • The balustrade's drawn run tops out at the deck's perimeter (you can't draw 12 lm around a 2 × 2 m deck), but the price always follows the stepper — the label prints the priced length. Documented here so the drawing and the ledger can't be read as disagreeing.

Conversion decisions

  • Planner beside the hero copy, price on the boards. The 1200 × 750 thumbnail is the commercial argument, so the $4,080 badge sits in the artwork inside the first 750 px — a visitor (or a prospect imagining their logo up top) sees a priced deck before they scroll.
  • Planner → form handoff. "Send this deck to the quote form" carries size, timber, balustrade and price into the enquiry textarea — the demo interaction becomes a warmer lead, and the fields a real business needs (name, phone, suburb, job type) stay short.
  • Click-to-call everywhere a thumb lands: header tel link, hero CTA, and a sticky call/quote bar at mobile widths with 44 px targets.
  • Honest floors beat teaser rates. The 6 m² minimum is stated in the grid, in the planner note, and in the model — no scenario exists where the page's cheapest number can't actually be bought.
  • Confirmation is a designed state: hidden on load and on invalid submit; a valid submit swaps the form for a confirmation panel with the received scenario echoed back. No fake network round-trip.

Local SEO we'd implement for the real business

This demo page ships only honest WebPage/BreadcrumbList structured data naming it a demonstration — fictional business schema in a real index would be dishonest markup. For a real carpentry client we'd ship the schema below. Carpentry has no exact schema.org subtype, so the honest top-level choice is the parent HomeAndConstructionBusiness:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HomeAndConstructionBusiness",
  "name": "Jarrahline Carpentry & Decking",
  "description": "Carpentry and decking across Perth — decks, doors,
    skirting and built-ins from an Osborne Park workshop.",
  "telephone": "+61-8-XXXX-XXXX",
  "url": "https://example.com.au",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Osborne Park",
    "addressRegion": "WA",
    "addressCountry": "AU"
  },
  "areaServed": ["Osborne Park", "Karrinyup", "Joondalup", "Morley",
    "Subiaco", "Fremantle", "Cannington", "Midland", "Rockingham"],
  "openingHours": "Mo-Fr 07:00-16:00",
  "priceRange": "$$",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9",
    "reviewCount": "87"
  },
  "review": {
    "@type": "Review",
    "author": { "@type": "Person", "name": "Real Customer" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Fed from the client's live Google reviews."
  }
}
</script>

For the real client this feeds from their actual NAP, licence numbers and live review stream — plus service-page schema per trade line. Job-management integrations we'd wire the form into: Tradify or Buildxact for quoting and job cards, Xero for invoicing. Their photos would replace nothing here — the procedural drawing stays as the estimator; their finished-deck gallery would sit beside it.

What would change for the real client

  • Real phone number, ABN, licence and insurance details replacing the reserved placeholder patterns.
  • The form posting to their inbox and Tradify/Buildxact pipeline, with spam protection and an SMS acknowledgement.
  • Their reviews feed (Google) replacing the demo review cards, marked up as real Review schema.
  • Their rates in the planner — the model is a config object; repricing it is a five-minute change.
  • A finished-work gallery and per-service pages once the landing page proves itself.

Iteration log

Pass 1 — Craft

Measured every palette hypothesis with WCAG arithmetic: ash/charcoal 13.9:1, white-on-jarrah 9.2:1, jarrah-on-ash 8.0:1, shaving-ink 6.3:1, muted ink 6.7:1 — all clear of 4.5:1, no two-token remedy needed. Drove the full worked-example set against an independently reimplemented oracle with the complete control vector pinned per scenario (rest $4,080; jarrah $6,720; composite $5,760; +4 lm balustrade $5,240; 5.0 m² clamp $2,040 with note; 6.0 m² boundary $2,040 without; demolition $4,656; demolition × resize intersection $5,820) — every figure matched the pinned arithmetic first try. The screenshot review caught what the 52 green asserts couldn't: the demolition tag sat struck-through by the tape-measure dimension line, and the balustrade wires grazed the area callout. Both labels moved to a stacked caption row below the tape zone, where nothing else lives at any deck size.

Pass 2 — Depth

Reasoned about the badge at the extremes: the 172 px price badge would overhang a 2.0 m-long deck's boards entirely, so it became adaptive — under ~3.3 m of drawn length it compacts (narrower plate, tighter type, "6 m² minimum billed" as the short form), verified on the 5.0 m² clamp screenshot where badge, note and boards all fit inside the fascia. Added one micro-interaction: the badge does a 320 ms settle-pulse on every repricing, so the number visibly lands. Second-read details already in the boards: seeded knots on real timber but never on composite, whose grain honestly flattens to a single embossed stroke; the display line re-words itself ("SEVENTEEN AND A HALF SQUARE METRES…") rather than just re-numbering. A rapid-fire burst — seven control clicks in one evaluate, no settle between — left probe, badge and board count consistent with the final state: the token-in-handler pattern held.

Pass 3 — Hardening

375 px masthead checked first (W18): wordmark right edge vs call-pill left edge compared explicitly — clear air, no wrap; no horizontal overflow on either page, and the guide's pricing table scrolls inside its wrapper instead of stretching the page. Empty submit (on a fresh navigation, so the prefill can't mask it) raises three validation states and keeps the confirmation panel hidden; a filled submit swaps form for panel — and the screenshot of that panel caught a copy defect the asserts passed: "New deck — New deck — 4.0 × 3.0 m…", the job-type select duplicating the prefill's opening words. The echo now drops the job label whenever the details already lead with it. Reduced-motion parks the sheen mid-deck with the deck fully drawn; the rAF delta is clamped at zero and capped; the loop pauses on hidden tabs. Removed one ornament (a planned compass rose in the drawing's corner — the tape measure already carries the drawing's authority; Chanel rule).