Generative Assets · Industry demo 266 · Patios · Perth

How Longshade Patios was made

Longshade Patios is a fictional Canning Vale patio builder — an industry demonstration by Sapience Analytics showing a WA patio and pergola company exactly what a conversion-first landing page looks like when the pricing is honest and the signature interaction does the selling. The page's single job: book a free design & measure.

The concept

A patio purchase is a square-metre purchase that most builders quote like a mystery. Longshade's whole personality is the opposite: the price does its maths in front of you. The signature Patio Planner erects a procedural SVG patio — stirrups, posts, beams, rafters, sheets — as you stretch the steppers, casts its 5pm shade across the paving, and prints the same honest arithmetic the services grid quotes. The art direction is a Canning Vale backyard at five in the afternoon: limestone paving in late light, Monument-grey steel, Deep Ocean sheets, the string line still up.

Palette

Limestone paving#F3F0E9

The ground — Perth paving in late light. Page background.

Monument grey#3C3E42

Structure and primary ink — the sheet colour half of Perth's roofs wear.

Steel shade teal#2E5E6B

Line/mark accent — Colorbond Deep Ocean and the cool inside the shade line. Dimension lines, shade fills, CTAs. Never body text on paving.

Deck-oil amber#B0743A

The oiled jarrah post wraps — active chips, focus rings, the string line.

Amber ink#8F5A26

Derived darker amber for links — #B0743A fails 4.5:1 as text on paving, so the ink/line split rule applies.

The ground + warm-accent combination is held away from the banned cream-and-terracotta default by giving the accent duty to painted-steel teal, setting the display face as an engineering grotesque, and keeping amber strictly secondary — every colour is argued from the build, not from taste.

Type

The Patio Planner

The signature is a single buildScene() function that re-renders a 760×470 SVG on every state change. Projection runs along the screen x-axis (46 px/m, so the profile reads in true elevation) and length recedes obliquely (11,−7 px/m), which is what lets a gable read as a real peaked section against the house wall while posts, rafters and sheet strips multiply along the depth. Style chips swap the roof profile maths — flat is a level plane, skillion raises the wall attachment by P×10px, gable lifts a mid-projection ridge — and roofing chips swap the sheet fills: solid Deep Ocean with a lit/shadowed slope split, translucent polycarb that lets the rafters show through, pale insulated panel with a visible thickness edge. The 5pm shade is the roof footprint cast along a fixed sun vector (+1.35x, +0.3y per unit height), pulsing between 0.44 and 0.58 opacity — never below the 0.4 visibility floor — and reduced motion pins it at 0.5, settled and complete.

The erecting choreography is staged per group — stirrups, posts, beams, rafters, sheets, then the shade, then dimensions — with the first render given the full 0.94s stagger and every subsequent redraw switched to a fast path (0.24s transitions, 0.28s max delay, ~0.52s total) via a firstDraw flag, so stepper taps feel snappy rather than theatrical. Second-read details: the outdoor table sitting on the paving that the shade finally reaches (and at 3×3 m, doesn't quite), the amber string line still strung along the post line, and a magpie that lands on the ridge only for gables of 9 m or more.

The pricing model

One formula, no site-specific branches: total = max($4,800, round(length × projection × (style rate + roofing modifier))). The roofing modifier is deliberately flat across styles — a documented pricing statement on the card ("same modifier, whatever the pitch"), per the spec's secondary-meter rule. When the clamp engages, the card says why in words: the footings, engineering and approval cost the same whether the roof is small or generous.

AnchorRateNotes
Flat Colorbondfrom $310/m²Roof m² = length × projection; supply + install incl. engineering, drawings, lodgement
Skillionfrom $350/m²Single raked plane
Gablefrom $420/m²Ridge at mid-projection
Polycarb roofing−$25/m²Flat modifier across all three styles
Insulated panel+$95/m²Flat modifier; services grid's "insulated from $405/m²" = flat $310 + $95
Minimum job$4,800Clamp floor = the services grid's "pergolas & shade structures from $4,800"

Measured outputs (from the running page, verified against an independent oracle)

ScenarioArithmeticCard shows
Rest state — gable 6.0 × 4.0, Colorbond24 m² × $420$10,080 ✓
Gable 6.0 × 4.0, polycarb24 m² × $395$9,480 ✓
Flat 3.0 × 3.0, polycarb9 m² × $285 = $2,565 → clamp$4,800 ✓ (reason on-card)
Skillion 10.0 × 5.0, insulated50 m² × $445$22,250 ✓
Gable 4.5 × 5.5, Colorbond24.75 m² × $420$10,395 ✓

Every figure above was read from the driven page by a puppeteer harness and asserted against a pricing oracle re-implemented from the spec in separate code — the spec's two worked examples ($10,080 rest, $9,480 polycarb) both matched exactly, and the cheapest reachable output equals the $4,800 services floor.

Conversion decisions

Local SEO we'd implement for the real business

This demo page carries only WebPage schema naming it a demonstration — fictional structured data in a real index is dishonest markup. For a real patio builder we'd ship LocalBusiness + Review schema fed by their actual details and review stream:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "@id": "https://longshadepatios.com.au/#business",
  "name": "Longshade Patios",
  "description": "Colorbond patios & pergolas — designed, engineered,
    council-approved and built across Perth.",
  "telephone": "+61 8 XXXX XXXX",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Canning Vale",
    "addressRegion": "WA",
    "postalCode": "6155",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -32.058, "longitude": 115.918 },
  "areaServed": ["Canning Vale","Willetton","Thornlie","Harrisdale","Perth"],
  "openingHours": "Mo-Fr 07:00-17: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": "Their real words, pulled from their real review feed."
  }]
}
</script>

Plus suburb-level service pages (patios Canning Vale / Willetton / Thornlie), a Google Business Profile wired to the same NAP, and FAQ schema on the questions above — the approval question alone is a featured-snippet magnet in WA.

What would change for the real client

Iteration log

Pass 1 — Craft

The first oblique-projection scene failed the screenshot review: with length on the x-axis and projection foreshortened at 13px/m, the gable read as a collapsed lean-to and the whole patio looked like a solar panel propped against a shed — every state assert was green while the drawing argued against the product (the rendered image is ground truth). Rebuilt the geometry projection-first: projection along x at 46px/m so flat/skillion/gable profiles read in true elevation, length receding obliquely. Also merged the two steppers into one labelled row (the old layout wasted a control row and pushed the scene down), fixed the mobile header phone chip wrapping to two lines with white-space:nowrap, and drove all 6 FAQ items, every chip and both steppers headlessly — 41 asserts green including empty-submit (3 invalid fields on fresh load) and filled-submit confirmation.

Pass 2 — Depth

Enriched the signature: lit/shadow slope split on gable sheets, jarrah wraps on the posts, the alfresco sliding door on the receding wall, the table the shade "finally reaches" (deliberately only half-covered at 3×3 m — the metaphor prices the upsell), the magpie that lands only on ≥9 m gables, and the erecting stagger re-ordered to the trade's real sequence (stirrups → posts → beams → rafters → sheets → shade). Screenshot review caught the table colliding with the length dimension and the near post — moved the table deeper into the cast shade and floated the length dimension along the outer roof edge, clear of everything. Price card values were wrapping mid-equation; pinned them nowrap and capped the total box width.

Pass 3 — Hardening

375px masthead checked first by screenshot and by rect-comparison (brand right edge 184px vs phone chip left 224px — no collision); scrollWidth 375; sticky bar fixed in the bottom 140px with a 49px tel target; h1 + CTA + trust chip all inside the first mobile viewport. Reduced-motion path verified headlessly: all scene groups settled, shade pinned at 0.5 opacity, no transitions. Form phone pattern written v-flag-safe (all specials escaped) — zero console errors across every run. Scene groups animate opacity/transform via CSS on elements that carry no competing SVG presentation attributes, per the W16/W17 rule. Chanel rule: deleted a planned second sun-glow ornament and the dashed "same-week ring" label halo from the scene — the shade is the ornament. Final copy read done against the model: every price on the page traces to the six anchors.