Generative Assets · Industry Demos XVIII · site 302

How the Downpour Gutters & Guards demo was made

Build notes for the wave's one dark site — a storm rolling in at dusk over a Gosnells roofline. Back to the page · collection index.

Concept

Downpour Gutters & Guards is a fictional Gosnells gutter-replacement operator built for homeowners staring down the June rains — and buyers told "the gutters are shot" on a building report. The page has one job: a replacement-estimate enquiry with the metres already on the meter. The drama lives in the weather; the page stays calm and ruled beneath it, speaking real roof-plumbing vocabulary — quad profile, Colorbond, Monument to Surfmist.

Palette — argued from the storm and the rusted quad

Storm slate#22262D the page ground — dusk with the front coming in.
Zinc white#EAECEF body ink, 13.4:1 on the slate. New gutter steel.
Corrosion copper#D2803F the rust marks and CTAs — marks only, never small text.
Rain blue#7FB2D9 the rainfall, water flow-lines, rules and links.
Muted zinc#A9B0BA derived secondary ink, 6.9:1 — the ink/line split on a dark ground.

Dark-site discipline: every piece of body copy was probed against the slate ground (≥4.5:1 everywhere; the two inks measure 13.4:1 and 6.9:1), and the two accents are spent exclusively on marks, lines and large bold CTAs.

Type

Bitter 600/700 for display — a slab that holds weight on a dark ground the way a cast gutter bracket holds a quad. The typographic moment is the meter's own readout, "30 METRES OF QUAD", set as the panel headline with the count in rain blue. Source Sans 3 carries body and UI: legible at 16.5px on a phone in the rain, which is where this page would actually be read.

The signature — the Roofline Meter

An SVG house elevation under live procedural rain. The scene is rebuilt as one SVG template per state — wall, hip roof, quad gutter with a magnifiable bead line, 0–8 downpipes, a dimension line that reads the current metres — while a canvas overlay in the same 1000×560 coordinate space runs the weather: ~130 rain streaks with drift, rivulets running the roof plane, dashed water flow along the quad toward each downpipe's watershed, the fall down every pipe, and a splash ring at each shoe. With zero downpipes the quad visibly overflows — the honest picture. With the guard on, leaf specks tumble in, hit the mesh and shed off the front (the second-read detail). A copper-pulsed annotation marks the rust-through joint "you hear in June".

The ledger prices the scene live from the pinned anchors — $68/lm single storey, $86 double (stated on-card as an $18/lm access premium, not a different gutter), $120 a downpipe, $28/lm mesh — with a $1,700 total-level minimum whose note appears only when it binds (the boundary sits exactly at 25 lm / 0 downpipes / single / no guard). Metres and storeys pre-fill the enquiry form, so the demo interaction walks straight into the lead.

Engineering notes: every control handler bumps an animation token before the state swap, so in-flight entrance animations and settle timers invalidate cleanly under rapid-fire input; the canvas loop reads the live geometry object each frame (no stale closures over old downpipe arrays); the SVG gets entrance choreography on first draw only (26 ms stagger, 1.1 s cap) and snappy redraws after (8 ms, 380 ms cap); DPR is capped at 2, the loop pauses when the tab hides, and reduced motion renders one settled frame with the rain re-rolled above the roof silhouette. A window.__gutters probe exposes scenario, computed figures and a settled flag for state-gated QA.

Pinned pricing anchors

ItemRateNotes
Colorbond quad replacement, single storey$68 / lmsupplied & installed, old run disposed
Colorbond quad replacement, double storey$86 / lmthe $18 is an access premium, stated on-card
Downpipes, Colorbond to 3 m$120 eachswapped with the run
Aluminium mesh gutter guard$28 / lminstalled with the new gutters
Minimum job$1,700 billedtotal-level clamp; note shown only when binding
Gutter cleaningfrom $190single storey, flat to 30 lm — deliberately not in the meter
Leak & overflow repairsfrom $190half-day minimum stated
Fascia replacementno numberdesigned price-less state — quoted on inspection

Every displayed figure was measured from the running page and cross-checked against an independently reimplemented oracle of these anchors: rest state 30 lm / 4 downpipes / single / guard off = $2,520; guard on = $3,360; double storey = $3,060; 15 lm + 2 downpipes rates to $1,260 and bills at $1,700 with the note; exactly 25 lm / 0 / single / off lands on $1,700 with no note. The estimator's cheapest reachable output equals the services grid's "from $1,700" floor, and all totals display to the whole dollar.

Conversion decisions

Local SEO we'd implement for the real business

This demo page ships only WebPage/CreativeWork structured data, because fictional business schema in a real index is dishonest markup. For a real gutter operator we'd ship a RoofingContractor profile — schema.org's exact construction-family subtype for roof plumbing — wired to their real NAP, licence, hours and review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "RoofingContractor",
  "name": "Downpour Gutters & Guards",
  "description": "Colorbond gutter replacement, guards and downpipes across the Perth metro.",
  "telephone": "+61-8-XXXX-XXXX",
  "url": "https://www.example.com.au",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Gosnells",
    "addressRegion": "WA",
    "postalCode": "6110",
    "addressCountry": "AU"
  },
  "areaServed": ["Gosnells","Thornlie","Maddington","Canning Vale","Perth"],
  "openingHours": ["Mo-Fr 07:00-16:00","Sa 08:00-12:00"],
  "priceRange": "$$",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9",
    "reviewCount": "137"
  }
}
</script>

Panel note: the top-level @type is RoofingContractor — an actual LocalBusiness-family organization subtype, not a specialty enumeration. The aggregateRating block only ships when it's fed by the client's genuine review source (Google Business Profile via API, or a reviews platform), never typed in by hand.

Iteration log

Pass 1 — Craft

The screenshot review caught a real ship-blocker every DOM assert sailed past: the meter's control row used a viewport-width media query for its four-column layout, but the panel itself is only ~560px wide inside the hero grid — the guard switch was pushed clean out of the clipped panel and the "Double" chip was cut. Replaced with a wrapping flex row that composes at any panel width. Also softened the lit dusk window from 0.5 to 0.16 alpha (it read as a tan cardboard rectangle, louder than the signature), and re-verified the dark-ground contrast pairs: body 13.4:1, muted ink 6.9:1, copper and rain blue confined to marks, lines and large bold CTAs.

Pass 2 — Depth

The native-resolution scene review showed downpipes crossing window glass at several counts — pipes now nudge to the nearest clear wall either side of each pane. Confirmed the guard's leaf-shedding second read and the zero-downpipe overflow branch on screen, and added the total-figure tick (a 450 ms scale-and-colour breath when the billed figure changes — skipped under reduced motion and on first draw). Drove every stepper, chip and toggle against the independent oracle: $2,520 / $3,360 / $3,060, the $1,260→$1,700 clamp with note, the exact 25 lm boundary with none, stepper floors and caps, and two rapid-fire bursts (a dozen dispatched clicks in one evaluate, no settle) with zero console errors and oracle-matching final state.

Pass 3 — Hardening

Fixed the reduced-motion static frame: drops that spawned below the roof silhouette were being respawned off-canvas, thinning the rain to nothing over the house — they now re-roll above the silhouette before the single draw. Removed the map's echo coastline stroke (the one ornament too many). Verified at 375px: masthead row clear of collisions, h1 + quote CTA above the fold, sticky call bar inside the bottom 140px, zero horizontal overflow on both pages; the guide's pricing table ships in its scroll wrapper. Focus rings on every control, DPR capped at 2, rain paused on hidden tabs, form validation v-flag-safe (required + minlength, no brittle pattern attributes), and the confirmation panel probed for its visibility transition — hidden on load, hidden on empty submit, shown only after a valid one.

What would change for the real client