Clearpane — build guide
View the site  ·  Index

Generative Assets · Wave 30 · Industry Demos XIX

Making Clearpane — a window cleaning page that prices the visit before the phone rings

Clearpane Window Cleaning is a fictional Como operator serving homeowners before a sale or a party, and shopfront owners who want a standing fortnightly round. The page has one job: an enquiry with the pane count already on the meter — the Pane Board turns "how much roughly?" into a number, then hands that number to the form.

The concept

The whole page argues from light through clean glass: pale-sky ground, glass-tint panels, deep glass-blue chrome, and a signature that literally wipes panes clean. Residential and shopfront are genuinely different businesses — different rates, different minimums, different rhythms — so the Board carries two modes rather than pretending one meter fits both. The fortnightly toggle reprices honestly: a standing round is cheaper because the glass never gets bad.

Palette

#EDF5F9 · morning skyPage ground — the sky a clean pane reflects.
#26323B · frame slateBody ink, 12.3:1 on the ground. Window frames, the squeegee blade.
#2C6E91 · deep glass blueCTAs, buttons, links — 5.1:1 on sky, 5.6:1 under white text. Never small text on light panels.
#9FD0E4 · pane tintGlass fills, rules, marks. The smudge-to-clear gradient lives between this and near-white.

The ink/line split holds throughout: the accent blues draw lines, fills and buttons; small text always sits in frame slate or the derived muted ink #435562 (7.0:1 on sky).

Type

Jost 600–700 for display — clean geometric with a signwriter-modern feel, right for a trade that letters its own van. Nunito Sans for body — rounded, legible, friendly at 16.5px. The display moment is the per-visit price set huge inside a drawn pane, with "a visit" beneath it — the number is the headline, exactly as it should be on a quote tool.

The Pane Board

An SVG facade built entirely in code. Residential mode draws a two-storey elevation — roof, wall, door, and a window grid per floor; shopfront mode swaps to a street run — fascia, scalloped awning, glass door and a panel row. A layout function packs any count (0–30 ground, 0–20 upper, 1–40 panels) into centred rows, so the elevation always reads as a plausible building rather than an abstract grid.

The squeegee is the motion signature. One rAF clock (delta clamped at zero and capped, per the collection's W29 lesson) drives a deterministic wipe cycle: the blade wipes each pane top-to-bottom, hops to the next with a smoothstep arc, and every pane's smudge opacity is a pure function of time-since-its-wipe within the cycle — no per-pane mutable state, so the scene can be rebuilt at any instant without desync. Freshly wiped panes carry a diagonal glint that fades as the smudge creeps back; a droplet runs off the pane wiped just before the current one. Panes are wiped upper floor first, so the 7-second thumbnail settle always catches the blade mid-wipe on an upper pane — the rest state is designed, not lucky.

Every control bumps an invalidation token in its handler before touching state (the W25 stale-closure rule), and rebuilds redraw with a two-speed stagger: the first draw earns the full entrance (26 ms per pane), subsequent state changes snap in at 11 ms per pane capped ~520 ms. A state probe at window.__windowcleaning exposes the scenario, computed figures, wipe position and a settled flag for QA.

Honest pricing — anchors, minimums, worked examples

Both modes carry their own minimum, stated in the meter's unit and billed at the selected rate. The estimator's cheapest billed outputs equal the services grid's floors ("residential visits from $180", "shopfront rounds min $90"). Hard-water stain treatment is a designed price-less state — mineral etching varies too much to price blind — and solar cleaning is deliberately outside the meter, stated on-card. All figures below are measured from the running page and cross-checked against an independently reimplemented oracle.

ScenarioArithmeticBilledMinimum note
Rest state — residential, 12 ground + 6 upper, screens ON144 + 96 + 54 = 294$294
Same house, screens OFF144 + 96 = 240$240
15 ground only, screens OFF15 × 12 = 180$180none — exactly at the minimum
12 ground only, screens OFF12 × 12 = 144$180shown — below the $180 minimum
Shopfront, 14 panels, one-off14 × 9 = 126$126
Shopfront, 14 panels, fortnightly14 × 6 = 84$90shown — below the $90 minimum
Shopfront, 15 panels, fortnightly15 × 6 = 90$90none — exactly at the minimum
Shopfront, 10 panels, one-off10 × 9 = 90$90none — exactly at the minimum
AnchorRateNotes
Residential ground-floor window$12 eachboth sides, sills wiped
Residential upper-floor window$16 eachpole/ladder access difference, stated on-card
Screens & tracks add-on+$3 per windowapplies to every counted window; residential only
Residential minimum visit$180 billedreachable at exactly 15 ground windows
Shopfront panel, one-off$9 per panelminimum reachable at exactly 10 panels
Shopfront panel, fortnightly round$6 per panelminimum reachable at exactly 15 panels
Shopfront minimum visit$90 billedapplies in both rates, billed at the selected rate
Solar panel cleaningfrom $160flat to 20 panels — outside the visit meter by design
Hard-water stain treatmentno numberquoted on sight — the declaration is the price line

Conversion decisions

Local SEO we'd implement for the real business

The live demo page carries only honest WebPage/CreativeWork schema naming it a demonstration. For a real Clearpane we'd ship the block below — schema.org has no window-cleaning subtype, so ProfessionalService is the correct organization type, with the service itemised. Reviews would come from the client's real Google Business Profile, never hand-written.

{
  "@context": "https://schema.org",
  "@type": "ProfessionalService",
  "name": "Clearpane Window Cleaning",
  "description": "Residential and shopfront window cleaning across the
    Perth metro — pure-water pole system, screens and tracks,
    standing fortnightly shopfront rounds.",
  "url": "https://clearpane.example.com.au",
  "telephone": "+61-8-9000-0308",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Como",
    "addressRegion": "WA",
    "postalCode": "6152",
    "addressCountry": "AU"
  },
  "areaServed": ["Como", "South Perth", "Applecross", "Victoria Park",
    "Subiaco", "Cottesloe", "Fremantle", "Scarborough", "Joondalup",
    "Canning Vale", "Rockingham"],
  "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
    "opens": "07:00", "closes": "17:00"
  },
  "priceRange": "$90–$600",
  "makesOffer": [
    { "@type": "Offer", "itemOffered": { "@type": "Service",
      "name": "Residential window cleaning" }, "priceSpecification": {
      "@type": "PriceSpecification", "minPrice": 180, "priceCurrency": "AUD" } },
    { "@type": "Offer", "itemOffered": { "@type": "Service",
      "name": "Fortnightly shopfront round" }, "priceSpecification": {
      "@type": "PriceSpecification", "minPrice": 90, "priceCurrency": "AUD" } }
  ],
  "aggregateRating": { "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "187" }
}

What changes for the real client

This demo swaps cleanly onto a real operator's stack. Job cards, recurring fortnightly rounds and invoicing would come from ServiceM8, Jobber or AroFlo — the enquiry form posts straight into the job queue with the Pane Board's scenario attached, and the fortnightly round becomes a genuine recurring booking with SMS "on our way" texts. Reviews feed live from Google Business Profile; invoices reconcile through Xero. Their photos replace nothing — the procedural facade stays, because it's the quote tool, not a stock-photo placeholder.

Iteration log

Pass 1 — Craft

The $294 display pane — the page's display moment — rendered at ~790px in the 1200×750 capture, below the thumbnail fold. Moved the ledger directly under the facade (price first, steppers after); it now sits at 574px and the thumbnail carries the number. Removed the price-pane's radial "bubble" ornament — the diagonal glass-glint gradient was already doing that job. Confirmation copy gained a fallback ("your job") for an emptied count field. Masthead measured at 375: wordmark right edge 149px vs call-chip left edge 221px — clear air, no collision.

Pass 2 — Depth

Added the wipe-flash micro-interaction: every repriced total sweeps a diagonal white band across the price pane — the same visual language as the squeegee, so the board "cleans" its own number. Added the second-read droplet that runs off the previously wiped pane, driven from the same deterministic clock. Cleaned panes now carry a glint that decays as the smudge creeps back, which makes the wipe cycle legible at a glance rather than just busy.

Pass 3 — Hardening

Squeegee and droplet now hide when the board has zero panes (a 0-window residential scenario is legal and bills the $180 minimum honestly). Reduced-motion renders a settled mid-wipe frame — probe settled, steppers still repricing, asserted headlessly. The full harness drives every control: both mode chips, all three steppers, both toggles, empty and filled submits on a fresh navigation, the four exact-boundary crossings (15 ground = $180 · 10 panels one-off = $90 · 15 fortnightly = $90 · 14 fortnightly = $84 → $90 with note), plus a twice-run rapid-fire drive (mode swaps, six stepper clicks, toggle flips in a single evaluate) against the token-invalidation guards — 35/35 asserts, an independently reimplemented pricing oracle agreeing at rest, at the residential boundary and at the fortnightly crossing, and zero console errors at 1200 and 375. scrollWidth 375 on both pages; every guide table lives in a .table-scroll wrapper.

← Back to the Clearpane site  ·  Generative Assets index