Generative Assets · Industry demo build guide

How the Catchline Rainwater demo was built

Catchline Rainwater is a fictional Mundaring operator supplying and installing rainwater tanks, pump kits and rain-to-mains plumbing across the Perth hills. The page has one job: an install request with the tank, roof, pump and extras already priced — and the honest annual-capture figure that sells it. The audience is the hills family off scheme water, the gardener sick of summer bills, the new build plumbing rain to the laundry.

The Catchment Calculator

The signature is a drawn SVG hills house in light rain: corrugated roof, gutter, a charged downpipe running to a poly tank on a pad, rain streaking down, water sheeting to the gutter and a drawn stream filling the tank while its level breathes upward on a slow loop. Every control redraws the scene: the roof stepper (50–400 m², ×25) widens the drawn roofline — the house grows to 250 m² and then holds while the dimension tag keeps printing the true figure; the tank chips swap between a squat 5 kL, the classic 13.5 kL round and the 23 kL flat-wall, each with its kL cast on the wall; the pump chips draw a gravity tap, a garden pump kit or the house-supply pump with twin filters and a pipe run into the wall; the toggles draw the first-flush diverter on the downpipe and the rain-to-mains valve box on the wall.

The price lives inside the artwork as a zinc gauge-plate riveted beside the tank: the installed price, the capture line, and — when the maths asks for it — the fills-a-year note. On phones the plate docks statically below the drawn scene so it never covers the tank. The whole scene is rebuilt synchronously in each control's handler (the animation token is bumped before the state swap), with entrance choreography on the first draw only and a snappy ~360 ms stagger cap on every redraw after that.

The honesty rules in the numbers

Worked anchors (all measured from the running page)

ScenarioPriceCaptureFills note
Rest: 23 kL · 200 m² · house pump · diverter · switchover$5,660≈ 152,000 Labsent (top tank)
13.5 kL, same everything$4,410≈ 152,000 L"about 11 times a year — the 23 kL…"
5 kL · 50 m² · no pump · no extras (grid floor)$1,800≈ 38,000 L"about 8 times a year — the 13.5 kL…"
13.5 kL · 100 m² · garden kit · diverter (switchover locked)$3,260≈ 76,000 L"about 6 times a year…"
23 kL · 400 m² · house pump · both extras$5,660≈ 304,000 Labsent — roof never prices

Palette — argued from wet galvanised iron

A hills winter morning: gum-grey ground, ironbark-dark ink, rain-blue for the water and the CTAs, zinc for the corrugation lines and the rain itself. Every ratio below was measured with WCAG arithmetic from the shipped hexes.

#E9EDEA gum greypage ground — morning mist over the scarp
#242B29 iron darkbody ink — 12.23:1 on the ground
#2E6E93 rain blueCTA fill, white labels 5.57:1 · hover #265D7D, 7.13:1
#1F4E6B blue inkblue-coloured copy — 7.53:1 ground, 8.90:1 white
#9FA8AD zinclines and rain only (2.05:1 — never text)
#5A666D zinc inkzinc-coloured small copy — 5.00:1 ground
Pair (as shipped)MeasuredVerdict
#242B29 body ink on #E9EDEA ground12.23:1spec said 12.2 — holds
#FFFFFF on #2E6E93 CTA / #265D7D hover5.57:1 / 7.13:1spec said 5.6 / 7.1 — holds
#2E6E93 links on ground · on white cards4.72:1 · 5.57:1spec said 4.7 / 5.6 — holds
#1F4E6B blue-ink on ground · white7.53:1 · 8.90:1spec said 7.5 / 8.9 — holds
#5A666D zinc-ink on ground · white · #F5F8F65.00:1 · 5.91:1 · 5.52:1holds everywhere it's used
Gauge-plate sub-label — zinc-ink on the plate metal4.17:1failed → minted plate-ink #414C54: 5.01:1 on the deepest plate tone
Selected-chip small copy #EAF2F7 on #2E6E934.92:1first draft #D8E7F0 measured 4.41 → re-minted
Footer copy #C9D2CE · trust strip #DCE4E0 on #242B299.36:1 · 11.16:1holds

Type

Bitter 600/700 for display — a sturdy slab that reads like a stencilled tank gauge; it carries the wordmark, the headings, the plate price and the kL cast on the tank wall. Mulish is the workhorse for everything else: controls, ledger, forms, footer. The typographic bravery moment is the display line over the drawn house — the running capture figure set huge in slab caps ("152,000 LITRES A YEAR OFF YOUR OWN ROOF"), rebuilt live from the model so the bravado is always arithmetically true.

Techniques

Conversion decisions

Local SEO we'd implement for the real business

The demo page ships only WebPage/BreadcrumbList schema naming it a demonstration — fictional structured data in a real index would be dishonest markup. For the real client we'd ship Plumber (the install trade is plumbing — the exact schema.org organization subtype, not a generic LocalBusiness) with real NAP, geo, hours and a genuine review feed:

{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "name": "Catchline Rainwater",
  "description": "Rainwater tanks, pumps and plumbing across the Perth hills.",
  "url": "https://catchlinerainwater.com.au",
  "telephone": "+61 8 XXXX XXXX",
  "image": "https://catchlinerainwater.com.au/media/install-23kl.jpg",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Mundaring",
    "addressRegion": "WA",
    "postalCode": "6073",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.90, "longitude": 116.17 },
  "areaServed": ["Mundaring", "Darlington", "Glen Forrest", "Mount Helena",
                 "Chidlow", "Kalamunda", "Roleystone"],
  "openingHoursSpecification": [{
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
    "opens": "07:00", "closes": "16:30"
  }],
  "hasCredential": "Licensed plumbing contractor — Plumbers Licensing Board WA",
  "aggregateRating": { "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "87" },
  "review": [{
    "@type": "Review",
    "author": { "@type": "Person", "name": "Real Customer" },
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "reviewBody": "Pulled from the live review feed, never hand-written."
  }]
}

What else changes for the real client: their install photos replace the drawn scene's supporting role (the calculator stays — it converts), reviews come from their Google profile feed, the request form books straight into ServiceM8 or Tradify as a site-look job, invoicing runs through Xero, tank stock and lead times come from supplier feeds (the Bushmans/Kingspan kind), and the capture widget reads live BoM rainfall for their actual gauge rather than a hedged long-term average.

Iteration log

  1. Pass 1 — Craft

    • Measured all 34 shipped colour pairs with WCAG arithmetic. The spec's computed figures held to the second decimal (12.23, 5.57, 7.13, 4.72, 7.53, 8.90, 5.00), but two pairs the spec never saw failed: the gauge-plate's sub-label (zinc-ink on plate metal, 4.17:1) got a minted plate-ink #414C54 (5.01:1 on the deepest plate tone), and the selected chip's small copy (4.41:1) was lifted to #EAF2F7 (4.92:1).
    • Masthead book button rendered a double word-gap (flex gap + a stray  ) — restructured into long/short label spans ("Book a site look" / "Site look").
    • Scene label collisions fixed at draw-coordinate level: the mains line originally rose through the window at small roof widths (re-routed to enter the valve box from below), and the first-flush label sat on the charged pipe run (moved below the ground line, beside the flush point).
  2. Pass 2 — Depth

    • Screenshot review caught the ship-blocker no assert saw: the gauge plate covered the entire 23 kL tank at desktop widths. Widened the viewBox 980→1080 to give the plate its own margin, re-anchored it so it overlaps only the tank's top corner (per-tank bottom offsets keep it "riveted" to each tank height), and docked it statically below the scene on phones — the drawn subject is never covered at any width.
    • Moved the gravity tap from the tank's left base (where it tangled with the charged riser) to a clear stand on the right, and labelled it and the flush point under the ground line.
    • Second-read detail: a rain gust rolls through roughly every fifteen seconds — streak speed swells and settles; the tank level breathes upward on a slow sine with an inlet ripple whose radius pulses.
    • Drove every worked example against an independently reimplemented oracle: 36-cell full sweep (3 tanks × 3 pumps × 2 × 2 toggles at 150 m²) plus the pinned scenarios, the fills boundary pair (13.5 kL × 50 absent / × 75 present), the switchover lock/restore in both directions (restores a deliberate OFF too), and the price-holds-while-capture-moves decoupling both ways. Zero model corrections — every spec figure survived.
  3. Pass 3 — Hardening

    • 375 masthead checked first: wordmark right edge clears the call button; the tag line and phone number drop out below 640; no horizontal overflow on either page (offender probe excludes overflow-x:auto ancestors).
    • Rapid-fire drive — ten chip/stepper/toggle clicks in one evaluate, twice over with no settle — passed clean; the scene rebuild is synchronous in the handler with the token bumped before the swap, so there is no in-flight animation to race.
    • Reduced-motion path renders the settled wet scene with the model live and settled arriving in ~30 ms; empty submit raises validation with the confirmation panel held hidden, and a filled submit shows the designed panel (verified on a hard reload so the pre-filled setup line can't mask validation).
    • Chanel rule: cut the freestanding "mains" pipe label and a planned splash burst at the tank inlet — the dashed line into the valve box and the breathing ripple already carry the meaning.
    • Final copy read: Australian English, no filler; the guide's tables wrapped in .table-scroll; both pages carry the fictional-business colophon.

Catchline Rainwater is a fictional business — a rainwater tank, pump and plumbing industry demonstration designed & built by Sapience Analytics, part of the Generative Assets collection. Back to the site · Index.