Generative Assets · Industry demo guide · 312

How Saltbush Shade Sails was made

A fictional Wangara shade sail company, built as a conversion-first landing page demonstration — every visual procedural, every price argued, and a Shade Planner whose sun actually moves.

01Concept

Saltbush Shade Sails sells one promise — Perth summer, minus the burn — to households with a west-facing alfresco, a bare pool surround, or a trampoline cooking in the open. The page's single job is a measure-and-quote enquiry with the sail's size and fabric already decided, so the signature is a top-down Shade Planner: a yard, a sail, a sun you can drag from 9 am to 5 pm, and a price that sits on the drawing itself. The shade is also the art direction — one marine-navy plane cutting a bleached-sand layout, poster-flat.

02Palette — argued from the sail against the summer sky

Bleached sand#F4E9D6 — page ground; the paving at 1 pm.
Shadecloth ink#26221C — body text, 12.4:1 on the sand.
Marine navy#1F4E79 — CTAs, the drawn sail, links. Chrome and fills, never small text on sand.
Sun amber#E8A13C — the sun arc, marks, dimension callouts. Lines and marks only.
Amber ink#B87817 — the derived darker token for amber-coloured rules and tiny labels (the ink/line split).
Cast shadow#1D2A38 — the shadow plane at opacity 0.62, never below the 0.55 visibility floor.

The amber never carries small text — dimension labels use the darker #B87817/#8A6A2E ink cuts, keeping the sun colour for the sun.

03Type

Bricolage Grotesque (600–800) is the display face — sun-bleached poster energy with enough structure to price a job in. The one moment of typographic bravery is the masthead line: MINUS / THE BURN. set huge across two hard-broken lines with the sun-arc slider directly beneath it, so the first interaction on the page sits under the biggest words on the page. Figtree carries body copy, ledgers and forms — legible at 16.5px, friendly without being soft.

04Techniques — the Shade Planner

All SVG, no raster. The yard is a top-down procedural scene: paver and lawn <pattern> fills, a pool with drifting water lines, a north arrow, the house band along the alfresco edge. The sail is a quad whose edges are quadratic curves pulled 10% toward the centroid — the concave read of a tensioned membrane. Fabric chips swap its fill between a 45° knitted-hatch pattern (shade cloth) and a sheen gradient (PVC membrane).

The shadow is screen-consistent projection. The sun rides a quadratic Bézier across the top of the plan (9 am east-right to 5 pm west-left, north up — southern-hemisphere honest). The cast shadow is the sail polygon translated away from the sun's screen position, with length 30 + 36·|cos φ| px — long and westward at 9 am, short and south at 1 pm, long and eastward at 5 pm. Dragging the slider moves the shadow live; the ledger re-renders every input event to prove the total never moves.

Dual-speed, token-invalidated animation. First draw earns the entrance: layers fade in staggered while the shadow sweeps 1.2 s from its noon position to the 2 pm rest. Every later change tweens geometry in 340 ms. Every control handler bumps an animation token before the state swap, so an in-flight tween or shadow-sweep can never close over stale scene data — the rapid-fire QA drive (ten clicks in one evaluate) passes clean.

Posts and fixings are computed, drawn, and itemised. Every sail has four corners; corners without a new $680 post fix to existing structure at $140 — so fixings = 4 − posts, never a separate control. House-side corners take fascia brackets (dashed ties to the alfresco edge), yard corners take cored posts (offset ring marks), and the ledger lists both lines with their arithmetic.

Second-read detail: a small top-down dog trails the shadow with an eased chase loop — wherever you drag the sun, the dog finds the shade. No caption; it's for the second visit.

05Honest numbers — measured, not asserted

Every figure below was measured from the running page by the headless harness and cross-checked against an independently re-implemented oracle of the pinned anchors ($95/m² cloth, $160/m² PVC, $680 post, $140 fixing, $1,700 minimum billed):

ScenarioArithmeticMeasuredMinimum note
Rest — 5 × 6 m cloth, 2 posts, 2 fixings2,850 + 1,360 + 280$4,490hidden
Same sail, waterproof PVC4,800 + 1,360 + 280$6,440hidden
4 × 4 m cloth, 4 posts (freestanding)1,520 + 2,720 + 0$4,240hidden
Boundary — 4 × 3 m cloth, 0 posts, 4 fixings1,140 + 560 = exactly the floor$1,700hidden — no note at the boundary
3 × 3 m cloth, 0 posts, 4 fixings855 + 560 = 1,415 → billed at floor$1,700shown
Sun slider 9 am → 5 pm, any scenarioshadow geometry changes onlyunchanged"The sun moves, your quote doesn't."

The services grid floor ("shade sails from $1,700 installed") equals the meter's cheapest billed output, and the $1,700 boundary is exactly reachable from the steppers at 4 × 3 m with 0 posts — so the no-note-at-boundary semantic is asserted at a real grid point. Commercial structures print no number at all: spans and footings drive them, so they're quoted on drawings — a designed price-less state, not missing data.

06Conversion decisions

  • The slider under the headline. The first thing the page invites you to do is play with the sun — and the toy is the argument: shade moves all day, so a fixed structure has to be measured, not guessed. The planner card holds the counter-statement where the price lives: "the sun moves, your quote doesn't."
  • The price lives inside the artwork. The $4,490 badge sits on the yard plan itself, inside the first 750px at 1200 wide — the thumbnail is the commercial argument.
  • Planner → form handoff. Dimensions and fabric pre-fill the enquiry form, so the demo interaction becomes a warmer lead: the visitor's sail is already on the ticket when they hit "Request my measure & quote".
  • Form fields are the trade's questions: name, phone, suburb, approximate dimensions, fabric, and "what's it shading?" (alfresco / pool / driveway / play area) — exactly what a sail company asks before a measure. Empty submits surface native validation; a valid submit shows a designed local confirmation ("we'd call you back within one business day") with no fake network round-trip.
  • Mobile-first call path: tel: link in the masthead and a sticky call/quote bar at 375px, both solid-backgrounded (no backdrop-filter on conversion chrome).
  • The $1,700 minimum is explained, not hidden — an FAQ answers "why", the note appears only when it actually binds, and re-tensions (from $240) are explicitly outside it.

07Local SEO we'd implement for the real business

This demo page carries only WebPage/CreativeWork structured data naming it a demonstration — fictional business schema in a real search index would be dishonest markup. For a real client we'd ship HomeAndConstructionBusiness (schema.org has no shade-structure subtype — it's the correct LocalBusiness-family choice) plus a genuine review feed:

<!-- would-ship schema, real client only — never on a fictional demo -->
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HomeAndConstructionBusiness",
  "name": "Saltbush Shade Sails",
  "description": "Custom shade sails and waterproof structures across Perth.",
  "telephone": "+61-8-9000-0312",
  "url": "https://saltbushshadesails.com.au",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Wangara",
    "addressRegion": "WA",
    "addressCountry": "AU"
  },
  "areaServed": "Perth metropolitan area",
  "openingHours": ["Mo-Fr 07:00-16:00", "Sa 08:00-12:00"],
  "priceRange": "$1,700–$12,000",
  "review": {
    "@type": "Review",
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "author": { "@type": "Person", "name": "— real customer, real feed —" },
    "reviewBody": "Pulled live from the client's Google Business Profile."
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9",
    "reviewCount": "— measured, never invented —"
  }
}
</script>

Alongside the schema: a Google Business Profile wired to the reviews block, suburb-level service pages only if the client genuinely services them, and honest titles ("Shade sails Wangara & Perth metro — from $1,700 installed") that match the page's real pricing.

08Iteration log

Pass 1 — Craft

Drove the full assert suite first: rest state measured $4,490, PVC swap $6,440, freestanding 4×4 at $4,240, both minimum-clamp boundary points (exactly $1,700 no note at 4×3/0 posts; $1,415 → billed $1,700 with note at 3×3), the sun sweep changing shadow geometry with the total pinned, empty/filled form submits, and the 375px masthead (wordmark right edge 227px vs call-chip left edge 243px — clear). Screenshot review then caught two visual defects no assert saw: the display line wrapped as "MINUS THE / BURN." (rebalanced to a hard "MINUS / THE BURN." break), and the Wangara star's WORKSHOP & SAIL LOFT caption collided with the Scarborough label on the metro map (Scarborough moved below the caption line). Also stripped a mangled dead CSS declaration in the footer rules.

Pass 2 — Depth

Added the second-read detail — the dog that trails the shade — then found it invisible at rest in the zoomed screenshot: its target point sat under the sail plane, so it was correct and unseeable. Moved the target to the shadow's leading edge, where the dog now visibly lies in the cast shade at every slider position, with a token-safe eased chase loop for single-jump slider changes (reduced motion snaps it). Gave the price badge a 190 ms scale pop whenever the billed figure changes — CSS transform on a group that carries no SVG transform attribute, keeping the W16/W17 split. Re-ran the drive suite including the ten-click rapid-fire: final state honest at 6×4 PVC, 1 post = $4,940.

Pass 3 — Hardening

Full re-drive at 1200×750, 375×812 and reduced-motion emulation: settled flag true with zero console errors on all three; scrollWidth 375 on both pages; sticky bar's tel: link inside the bottom 140px; signature and price badge bounding boxes both intersect the first 750px at 1200 wide; guide pricing table wrapped in its overflow scroller at build time. Phone pattern escapes every literal special (\( \) \+ \-) so it compiles under Chrome's v-flag. Chanel rule: removed one of the two heat-shimmer squiggles on the open paving — one carries the heat read; the pair crowded the sun arc's airspace. Final copy read end to end in the rendered page.

09What changes for the real client

  • Their jobs, not our drawing: the procedural yard stays as the quote toy, but gallery sections switch to the client's install photography, and the reviews block reads from their Google Business Profile feed.
  • Booking that lands in their tooling: the enquiry form posts into ServiceM8, Tradify or AroFlo (whichever runs their jobs) with the planner's scenario attached — size, fabric, posts, the visitor's ballpark — so the measure visit starts pre-briefed. Calendar-slot booking for measures if their workflow suits it.
  • Real numbers end to end: their actual rates in the planner (it's one pinned-anchor table), their ABN and any engineering certification references, real wind-region documentation per install area.
  • Measurement: call tracking on the tel: links, form-source attribution, and Search Console wired to the honest schema above.