Generative Assets · Industry demo 274 · Wave 23
Design and build notes for a welding & fabrication landing page — the dark site of Wave 23: an arc-lit Bibra Lake workshop at 9pm, and a quoter that prices the way the trade actually prices.
Beadline Welding & Fabrication is a fictional Bibra Lake welding and custom steel business — balustrade, driveway gates, trailer repairs, and a mobile rig covering the Perth metro. The audience is owners, builders and farmers who need steel made or mended; the page's single job is a fabrication quote request or a mobile callout. The whole page is lit the way the work is: one arc burning blue-white out of a near-black shed, sparks dying orange on the concrete.
The name is the trade's own signature — the "bead line", the row of stacked dimes a clean TIG hand leaves. The signature element renders it literally: a weld bead of stacked-dime dots progressing along the seam of whatever job you configure.
The spec's ink/line rule applied cleanly: arc blue measures ≈7.5:1 on workshop night, so it's allowed short labels and the CTA, but all body copy is set in mill silver with a derived #9BA3AC for secondary text — both clear 4.5:1 on every surface they sit on (night, panel, night-2). The CTA is an arc-blue fill with near-black text (≈7.7:1), so the brightest thing on the page is the thing that books work — exactly like the shed, where the arc is the only lamp that matters.
The signature is a procedural SVG bench scene that welds live. Job chips (balustrade / gate / trailer repair / mobile) swap the workpiece — drawn in mill-silver line-work on the dark bench — and a weld bead progresses along its seam. The bead is two stacked strokes: a soft arc-blue under-bead and a stroke-dasharray: 0.1 6.2 round-cap layer that renders the literal row of stacked dimes the brand is named for. The reveal is a clip-rect that follows getPointAtLength(), so the dime pattern never shifts as it grows (animating dashoffset would have fought the dime dasharray — and W15's stray-dot hazard never arises because the bead floor never reaches zero). The travelling arc glow is an SVG radial-gradient group repositioned each frame, flickering between 0.45 and 1.0 opacity — never below the 0.4 visibility floor.
Sparks are a canvas 2D particle system overlaid on the SVG (coordinates mapped through the fixed 720-wide viewBox scale): particles spawn at the bead head, fall under gravity, bounce once off the bench line, and cool from white-blue through flame to spark amber. DPR capped at 2, sized to container, resized on resize, and the rAF loop pauses on document.hidden. Under prefers-reduced-motion the scene renders settled: bead complete, glow steady, no sparks, no loop.
Second-read details: the spark rate is process-honest — mild steel runs MIG and throws a full shower; stainless is TIG work and barely sparks (the price card says the same thing in words: "the extra is the hand"). The scene caption carries the process (· MIG / · TIG). And every eight-to-thirteen seconds the whole shed lifts for a tenth of a second — the flash every welder knows, timed to stay clear of the 7-second thumbnail settle. Rest state holds the bead about two-thirds along the seam (measured p≈0.68 at the settle), so the thumbnail always catches the weld mid-pass.
Redraw is dual-speed per W21: the first render earns the entrance stagger (26 ms/element, capped 1.5 s); every subsequent chip or stepper change redraws at 8 ms/element, 260 ms transitions — measured 0.26 s in the pass harness. State probe window.__welder carries job, material, metres, price, billed metres, bead progress and live spark count.
Everything is metre-or-hour arithmetic from pinned anchors — the quoter runs the same model the copy quotes, and the harness verified the displayed card against an independently reimplemented oracle at rest and across nine driven scenarios.
| Job | Meter | Anchor | Floor |
|---|---|---|---|
| Balustrade — mild, powder-coated | $/lm | $310/lm | 5 lm min → $1,550 |
| Balustrade — stainless | $/lm | +$120/lm (TIG hand) | 5 lm min |
| Balustrade — aluminium | $/lm | +$60/lm | 5 lm min |
| Driveway gate — single ≤1.8 m | per leaf | from $1,450 | $1,450 |
| Driveway gate — double ≤3.6 m | per leaf ×2 | from $2,900 (pure doubling) | $2,900 |
| Gate material adders | per leaf | +$300 stainless / +$150 alu | — |
| Trailer & plant repair | $/hr | $140/hr | 2 hrs → $280 |
| Mobile site welding | $/hr + callout | $140/hr + $90 callout | 2 hrs → $370 all-in |
Model shape, stated deliberately: shop and mobile share the one $140/hr labour rate — mobile adds the callout and nothing else (a documented flat statement, not an invented gradient). Repairs and callouts price by the hour, so for those jobs the metres stepper is disabled with its reason on-page ("the clock is the honest meter here"); material chips stay live there because they still change the rendering and the process caption, and the card states in words that material doesn't change the clock.
This demo page ships only a WebPage schema naming it a demonstration — fictional structured data in a real index would be dishonest markup. For a real client we'd ship LocalBusiness + Review schema like this:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Beadline Welding & Fabrication",
"description": "Mobile welding and custom steel fabrication across the Perth metro.",
"telephone": "+61-8-XXXX-XXXX",
"address": {
"@type": "PostalAddress",
"streetAddress": "Unit X / XX Example St",
"addressLocality": "Bibra Lake",
"addressRegion": "WA",
"postalCode": "6163",
"addressCountry": "AU"
},
"geo": { "@type": "GeoCoordinates", "latitude": -32.09, "longitude": 115.82 },
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "06:30", "closes": "16:00"
}],
"areaServed": ["Perth", "Fremantle", "Rockingham", "Kwinana", "Canning Vale"],
"priceRange": "$$",
"aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.9", "reviewCount": "87" },
"review": [{
"@type": "Review",
"reviewRating": { "@type": "Rating", "ratingValue": "5" },
"author": { "@type": "Person", "name": "Real Customer" },
"reviewBody": "Real review text pulled from the client's Google profile feed."
}]
}
</script>
Drove the full model against an independent oracle: 35 asserts — rest card $2,580 (stainless 6 lm), mild $1,860, min-clamp at 3 lm billing $1,550 with the minus stepper disabling at the floor, the crossing landing exactly at 5 lm, gates $1,450/$3,500/$3,200, repair $280 (= services floor), mobile $370. Empty submit on a fresh load raised 4 validation signals and no confirmation; filled submit confirmed in the required lexicon. Screenshot review (1200×750 and 375) caught the scene caption colliding with the balustrade's dimension line — moved the caption to the top edge — and two garbled hex tokens from authoring were fixed before first serve. Harness itself needed the W20 treatment twice (a click swallowed by the sticky masthead, a stepper count miscounted): fixed the harness, never the site.
Made the sparks process-honest: mean airborne particles measured 97.2 on MIG mild vs 13.4 on TIG stainless, with the process named in the scene caption. Added the rare whole-shed arc flash (0.11 opacity, ~120 ms, first firing after the 7 s thumbnail settle). Screenshot review of the gate and trailer scenes caught the trailer floating across the bench line (grounded it, −12px, wheel now sitting on the line and the repair bead moved onto the lower drawbar chord), leftover sparks surviving a job swap (particles now clear on scene change), and finish fills too faint to read (gradient stops lifted). Verified dual-speed redraw at 0.26 s and the keyboard path on chips and FAQ.
375px masthead checked first: wordmark right edge 142px vs call button left edge 285px — no collision; scrollWidth clean at 375 on both pages, h1 + CTA + trust signal inside the first viewport. Reduced-motion emulated: bead renders complete (p = 1), glow steady at 0.55, zero spark particles, no rAF loop. Resize re-sizes the spark canvas; the loop pauses on document.hidden. Chanel rule: removed the second overhead rack from the scene backdrop — the shed reads darker and the arc brighter without it. Guide pricing table shipped in a .table-scroll wrapper at build time. Final sweep: one h1 per page, zero console errors across every driven state.