Boardwalk

Generative Assets · Industry Demos XXVI · site 341

Boardwalk Floor Sanding & Polishing — how it was made

A conversion landing page for a fictional Bassendean floor sander, built to show a real Perth trade what their own site could do: price the floor before the van leaves the yard, then book the site measure with the scope already filled in.

Concept

Boardwalk Floor Sanding & Polishing is a fictional business — Perth jarrah, blackbutt and pine floors sanded back to bare timber and finished in water-based polyurethane, two-pack gloss or hardwax oil, working metro-wide from Bassendean. The audience is the owner of a 1950s–70s home who has just lifted the carpet, the renovator who wants the floors done before the kitchen goes in, and the landlord between tenants. The page has one job: a site-measure booking with the area, finish and extras already priced.

The art direction is the workshop at 9am with the dust extractor running: sawdust-cream ground, walnut ink, sanded-jarrah CTAs, machine-grey linework. The whole page is designed to read like a floor half-sanded — one side grey and tired, one side glowing.

Palette — measured, not assumed

Every ratio below is WCAG arithmetic on the shipped hex values, measured in Pass 1. The spec's hypotheses landed within 0.3 of the measured figures; the one under-5 pair (jarrah on the ground) took the pre-minted two-token remedy rather than a palette shift.

sawdust cream
#F5F0E6page ground — the dust on everything
walnut
#2C231Dbody ink, ledger, footer
sanded jarrah
#9F5622CTAs and buttons, chip outlines, marks
jarrah fill
#84461Bbutton hover / deeper fill (pre-minted pair)
jarrah ink
#733C16links and accent-coloured copy on the ground
machine grey
#9DA7ADboard gaps, sander outlines, rules — lines only
grey ink
#5B666Deyebrows, captions, small grey copy
walnut soft
#4E423Asecondary body copy
Walnut #2C231D on sawdust cream #F5F0E6 (body)13.54:1
White on sanded jarrah #9F5622 (button labels)5.49:1
Sanded jarrah #9F5622 on the ground (spec ≈5:1 — under 5, so text uses the ink variant)4.83:1
White on jarrah fill #84461B (hover fill)7.31:1
Jarrah ink #733C16 on the ground (links, prices, h1 emphasis)7.75:1
Grey ink #5B666D on the ground (eyebrows, captions)5.18:1
Machine grey #9DA7AD on the ground — LINES ONLY, never text2.16:1
Walnut soft #4E423A on the ground (secondary copy)8.54:1
Sawdust cream on walnut (ledger, footer copy)13.54:1
#C7BDB1 ledger sub-copy on walnut · #E8C79A ledger note on walnut8.31:1 · 9.57:1
Error red #8F2D12 on paper #FBF8F17.76:1

Timber colours on the drawn floor — jarrah #8E3B22, blackbutt #C9A16A, baltic pine #E1B778 — are artwork, not text grounds; the on-floor timber tag and the price lid sit on paper panels so their walnut and grey-ink type keeps the ratios above.

Type

Bricolage Grotesque (700, 800 for the display line and the price) carries the headlines, the wordmark, the price lid and the display moment — a grotesque with a workshop's shoulders, wide enough to feel like a trade and sharp enough not to look like a hardware catalogue. Source Sans 3 does everything else at 17px, 16px in form fields, never below 13px. The typographic moment is the area set huge above the drawn floor — "ONE-TWENTY SQUARE METRES, BACK TO BARE" — which swaps with the scope chips and the stepper (twenty, sixty, one-twenty, one-oh-five, two hundred), the number words written the way a sander says them on the phone.

The signature — the Board Reveal

A drawn SVG plank floor in one-point perspective (vanishing point above the far wall), the boards running left to right with seeded butt joints and grain lines in machine-grey linework. The floor is drawn twice from the same seeded geometry: a grey, scuffed layer (scuff strokes, two old water stains, grey grain) and a timber layer held in <defs> and instanced twice with <use> — once clipped to the permanently-sanded strip on the left, once clipped to a polygon whose right edge is the reveal front. A drawn drum sander (housing, motor, drum, rear wheels, handle bar, dust bag, trailing cord) sits on a lane at depth z = 1.34 and sweeps the front from 20% to 80% of the room over ten seconds; behind it the grey boards become the selected timber's colour with the selected finish's sheen band. At the end of the pass the moving layer cross-fades out over 0.9 s while the sander fades back in on the left — the left-hand 20% strip never dims, so the floor reads half-tired, half-glowing at any capture instant (the 7 s settle measured the front at 0.61). Reduced motion renders a single settled frame with the front at 0.55.

Timber chips recolour the timber layer's polygons (CSS transition: fill .35s on the shared defs — the instances follow) and swap the on-floor tag; the price is pinned unchanged and the card says so. Finish chips rewrite the sheen gradient's stops (gloss: a hard bright core plus the window's four panes reflected in the floor; satin: a soft band; oil: a whisper of light with the grain opacity lifted to 0.62) and the sheen tag. Scope chips set the area stepper, and the area rebuilds the geometry — the far wall recedes and the row count grows from 9 rows at 20 m² to 18 at 200 m² — with a first-draw stagger of 42 ms/row (1.1 s cap) and a snappy 9 ms/row (380 ms cap) on every subsequent rebuild. The rebuild is synchronous inside the handler and the sweep loop reads the live scene object, so a rapid-fire chip run can never leave a stale closure over old rows; the row-reveal class is added unconditionally so a rebuild-then-recolour in one frame never leaves the floor blank. The rAF delta is clamped at zero and capped at 50 ms. The price lives on the floor as a paint-tin lid at the near-right, with a tight variant below 600 px (price only, scaled up 1.42×) so it never covers the drawn boards on a phone.

Pricing model — pinned anchors, measured outputs

LineRate / amountRule
Water-based polyurethane, satin or matt (3 coats)$42/m²sand, three coats and clean-up, per m² of floor
Two-pack polyurethane, gloss (3 coats)$46/m²same scope
Hardwax oil (2 coats, buffed)$52/m²same scope
Area stepper10–200 m² × 5scope presets 20 / 60 / 120 m² SET the stepper; the stepper stays live and never changes the scope chip
Minimum25 m²billed at the selected finish; note at 20 m² ("billed at the 25 m² minimum — a single room is a full day's set-up"), no note at 25 — the boundary is on the stepper grid
Timber chips$0jarrah / blackbutt / baltic pine change the colour, not the rate — stated on-card
Staining & colour tone+$12/m²× the BILLED area (the 25 m² minimum multiplies the stain line too); DISABLED on hardwax oil with reason; restore-on-return
Board repairs+$180 flatup to five boards, live at every combination; more than five quoted on inspection
Furniture moved & returned+$150 flatlive at every combination
New floors, parquetry, stairsdesigned price-less line, "quoted on inspection" — grid, ledger and FAQ

Toggle matrix

ControlWater-basedTwo-pack glossHardwax oil
Staining & colour toneLIVE · +$12 × billed m²LIVE · +$12 × billed m²DISABLED — "hardwax oils come tinted — pick the tone at the sample stage, no extra". Switching to oil locks stain OFF and keeps the prior choice; switching back to either polyurethane RESTORES it (asserted both ON→restored ON and OFF→stays OFF).
Board repairsLIVE +$180LIVE +$180LIVE +$180
Furniture moved & returnedLIVE +$150LIVE +$150LIVE +$150
Timber chipsLIVE at every combination, no price change; the probe's timber field, the board fills and the on-floor tag all change
Scope chipsset the stepper to 20 / 60 / 120; the display line and geometry follow the stepper

Worked examples — all measured from the running page and cross-checked against an independent oracle

Scenario (full control vector set explicitly)ArithmeticMeasured
Rest: whole house 120 m², jarrah, water-based, no extras120 × 42$5,040 · no note
Single room preset → 20 m², water-based25 × 42$1,050 · NOTE present
Stepper to 25 m², water-based25 × 42$1,050 · no note
Living & hall 60 m², two-pack gloss, stain ON60 × 46 + 60 × 12$3,480
Whole house 120 m², hardwax oil, repairs ON120 × 52 + 180$6,420 · stain disabled with reason
Single room 20 m², water-based, stain ON25 × 42 + 25 × 12$1,350 · NOTE present
Rest + furniture5,040 + 150$5,190
Rest + furniture + repairs5,040 + 150 + 180$5,370
Blackbutt / baltic pine at rest120 × 42$5,040 · fills and tag change
Grid floors: water-based / two-pack / oil at 25 m²25 × 42 / 46 / 52$1,050 / $1,150 / $1,300
Stain ON, water-based → oil → water-based6,480 → 6,240 → 6,480restore asserted
200 m², pine, two-pack, all extras200 × 46 + 200 × 12 + 180 + 150$11,930

Totals display to the whole dollar; every anchor and quantity is integer-safe by construction. The estimator's cheapest priced output per finish equals the services grid's "from" floor.

Conversion decisions

Local SEO we'd implement for the real business

The live page emits only WebPage, WebSite, CreativeWork and a BreadcrumbList naming it a demonstration — fictional structured business data in a real index would be dishonest markup. For the real Boardwalk we would ship this on the home page, fed from the actual reviews source:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HomeAndConstructionBusiness",
  "name": "Boardwalk Floor Sanding & Polishing",
  "description": "Timber floor sanding, polishing, staining and board repairs across Perth.",
  "url": "https://www.example-boardwalk.com.au/",
  "telephone": "+61 8 9000 0341",
  "priceRange": "$$",
  "address": { "@type": "PostalAddress", "addressLocality": "Bassendean",
               "addressRegion": "WA", "postalCode": "6054", "addressCountry": "AU" },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.9067, "longitude": 115.9439 },
  "areaServed": ["Bassendean","Bayswater","Maylands","Mount Lawley","Guildford","Morley","Midland","Perth"],
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification", "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
      "opens": "07:00", "closes": "17:00" }
  ],
  "hasOfferCatalog": { "@type": "OfferCatalog", "name": "Floor sanding services",
    "itemListElement": [
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Sand & polish, water-based polyurethane" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "42", "priceCurrency": "AUD", "unitText": "m²" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Two-pack polyurethane gloss" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "46", "priceCurrency": "AUD", "unitText": "m²" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Hardwax oil finish" }, "priceSpecification": { "@type": "UnitPriceSpecification", "price": "52", "priceCurrency": "AUD", "unitText": "m²" } }
    ] },
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "112" },
  "review": [
    { "@type": "Review", "author": { "@type": "Person", "name": "H. (Bayswater)" },
      "reviewRating": { "@type": "Rating", "ratingValue": "5" },
      "reviewBody": "Thirty years of carpet up, jarrah underneath, back to the colour of a good red in two days." }
  ]
}
</script>

Alongside it: a Google Business Profile pinned to the Bassendean workshop with the finish photos as the cover set, suburb-specific service pages for the top ten eastern suburbs, the FAQ marked up as FAQPage, and reviews syndicated from Google rather than typed in.

What would change for the real client

Iteration log

Pass 1 — Craft

Found: the header CTA "Book a measure" wrapped onto two lines at 375 (masthead is always the first collision); the display line broke "BACK TO / BARE" at 1200; the drawn sander was too small to read as a machine; the ledger's book button ran to two lines on a phone; the trust eyebrow wrapped; the satin sheen was nearly invisible.

Changed: a short "Book" label under 480 px with the full label above; display line stepped down to clamp(19–24 px) with balanced wrapping; sander enlarged to scale 1 on the z = 1.34 lane with the cord now leaving the motor housing rather than the grip; "Book the site measure"; eyebrow to "Bassendean · Est. 2010 · 5-year warranty"; satin core opacity to 0.34. Contrast measured on the shipped tokens (table above); jarrah on the ground read 4.83:1, so links and accent copy took the pre-minted #733C16 ink. Every worked example driven with the full control vector set explicitly and matched against an independent oracle — 15 scenarios, all exact.

Pass 2 — Depth

Found: the finish chips changed the sheen band but gloss did not yet look like gloss; the reset between sweeps read as a hard cut; nothing rewarded a second look.

Changed: the window on the far wall now reflects in the floor for gloss (four pale panes inside the sheen band, opacity 0.34; 0.10 for satin; nothing for oil, whose grain lines lift instead); the sweep now ends on a 0.9 s cross-fade in which the moving layer dims while the sander fades out at the right and in at the left, the permanent 20% strip never dimming; six sawdust puffs trail the drum with a sine flicker; the stepper value and the ledger total bump 12% on change; the freshly-sanded front carries a pale line and a dust haze ahead of it. Timber and finish chips token-invalidate the settle timer in the handler; the rapid-fire drive (twelve clicks in one evaluate, then a 48-click loop) ends on a definite asserted state with every row visible.

Pass 3 — Hardening

Found: the on-floor timber tag was unreadable at 375 at its desktop size and, scaled up, crowded the near-left; the badge's third ring was ornament; the tag and badge needed a label-collision sweep against the sander at both ends of its lane.

Changed: tight variant under 600 px — tag scaled 1.65× and lifted, badge 1.42× with the price only, positioned so the sander's housing clears the lid at 80% and the tag at 20% (checked at native resolution); the badge's inner ring removed (Chanel rule). Verified: zero console errors, one h1 on both pages, 375 scrollWidth 375 with the wordmark's right edge clear of the call button's left edge, sticky bar fixed within the bottom 140 px with a tel: link, hero h1 + CTA inside the first 667 px, signature and price lid inside the first 750 px at 1200, reduced-motion static frame at 0.55 with zero frames, form empty submit → 3 invalid + panel hidden, filled submit → panel shown, drive-then-hash liveness, guide tables in .table-scroll wrappers.

This is a demonstration build by Sapience Analytics. Want one pointed at your customers?

sapienceanalytics.com.au · danny@sapienceanalytics.com.au