Generative Assets · industry demonstration 419
How the Hollowbank Furniture page was made
Hollowbank is a fictional two-person furniture workshop in Bayswater whose competitors run on Instagram alone — no prices, no lead times, no way to start. The page has one job: turn a household thinking about a table into a booked workshop visit with the piece, the timber and a rough size already attached. Everything on it is procedural — the elevation, the grain, the map, the icons — and the whole thing is two self-contained files with no libraries and no images.
For the business owner reading this
Why this converts
- The primary call to action is “Book a workshop visit” and it appears in the masthead, in the hero, under the estimate, in the enquiry section and in the sticky bar on a phone — because on a $4,000 commission the sale is made standing at a bench with three boards in front of you, not on a two-minute phone call, so the phone is the fallback and the visit is the conversion.
- The six form fields are exactly the six things the maker needs before he can lay out samples — name, phone, suburb, piece, timber and a rough size or the room dimension — and nothing else, because every extra field on a considered purchase costs enquiries and this one already arrives half-quoted.
- The proof element answers the two questions this customer actually has, what it costs and when it lands, and it answers with a range and a lead time rather than a false-precision figure, so the page can publish a number without over-promising and the visit is framed as the thing that turns the range into a fixed price.
- The trust strip is specific rather than boastful — a year, a count of commissions, and the fact that every piece is signed and dated underneath — and the services grid names the timber each “from” price actually buys, which is the single most disarming thing a page in this trade can do.
- The result card argues against its own dearer option in one line (“Blackbutt is $210 less”), because a customer who has been shown what the cheaper board saves them feels they chose, and a customer who feels they chose turns up to the visit.
The proof element
Why the estimate answers with a range
A commission that has not been drawn yet cannot honestly be priced to the dollar. The room has not been measured, the boards have not been picked and the base has not been chosen. A page that prints “$4,300” against that is either guessing or is going to move the price later, and moving the price later is how this trade loses people.
So the card prints $3,950–$4,650 and 10–14 weeks, and it says in the same breath that the fixed price follows the workshop visit. The range is ±8 % of the midpoint rounded to $50; the midpoint is the licensed cell. That is enough to let a household decide whether they are in the market at all, which is the only decision the page is asking for.
The arithmetic, and where it is licensed
Five pieces × three timbers × three size bands is a 45-cell domain, and every cell the page can display is checked by a small node script before the page ships. The check proves that the price rises with size for every piece and timber, that jarrah > marri > blackbutt on all fifteen piece-and-size pairs, that every quoted range straddles its own midpoint, and — by sweeping rather than by hand-picking a cell — that the cheapest commission is $1,380 and the dearest is $6,270.
The services grid is not typed by hand either. Its “from” figures are rendered from the same model at load, so the grid and the estimate cannot drift apart, and the grid’s floor equals the estimate’s swept floor.
| Piece | Small | Medium | Large | Lead time |
|---|---|---|---|---|
| Dining table | $3,200 | $4,300 | $5,600 | 10–14 weeks |
| Sideboard | $2,600 | $3,400 | $4,200 | 9–13 weeks |
| Bed frame | $2,400 | $2,950 | $3,600 | 8–12 weeks |
| Desk | $1,900 | $2,450 | $3,100 | 7–10 weeks |
| Bench seat | $1,450 | $1,750 | $2,100 | 6–8 weeks |
Those are the marri figures. Jarrah is ×1.12 and adds a week; blackbutt is ×0.95 and adds nothing. Prices round to $10, ranges to $50. The rest state — a medium dining table in marri — is $4,300, $3,950–$4,650, 10–14 weeks, and that is the state the collection’s preview thumbnail is cut from.
Why the workshop visit is the conversion, not the phone call
Trades with a $200 ticket convert on a phone call. This one has a $1,400–$6,300 ticket and a consideration period measured in weeks, and the thing that closes it is a person putting their hand on a marri board next to a jarrah one. So the page is built to produce a booking, not a ring — the tel: link is present everywhere it should be and is styled as the secondary action every single time.
The technique
How the grain is generated
The elevation is plain SVG built at render time. The selected piece resolves to a short list of rectangles in a 540-unit box with a common floor line, scaled by the size band. Each rectangle is filled with the timber colour, then grained inside its own clipPath by three generators driven from one seeded pseudo-random stream:
- Growth rings. A band count derived from the board’s thickness, each ring a four-segment cubic with a jittered centre line and a jittered amplitude. The rings run along the length of the part, so a rail is grained across and a leg is grained down — which is how the board would actually have been cut, and it is the single detail that stops the drawing reading as a stack of filled boxes.
- Glue lines. A solid top is a glue-up, never one board that wide, so a table top gets a joint every 96 units. Each joint wanders, because a sawn edge is not a ruler.
- One cathedral figure per generous part — three nested arcs rising from the bottom edge at a position the seed picks.
The seed is a hash of piece + timber + size, so a given configuration always draws the same board — the page is genuinely deterministic and genuinely at rest, which is what the preview pipeline needs — but changing any one of the three re-cuts the timber. Change the size band and the glue lines land somewhere else, because the maker would have laid out different boards.
On top of that sits the joinery, at full opacity: through-tenons and draw-bore pins on the table and the bench, handles on the sideboard, pulls on the desk, rail bolts and a headboard groove on the bed. That is the part of the drawing that is not stylised away, because visible joinery is what the maker actually sells.
The second read
Low on the left upright of every piece there is a stamped H over a short date rule, drawn at half opacity. The trust line at the top of the page says every piece is signed and dated underneath; the drawing does it. Most people find it the second time they visit.
It is not to scale and it carries no dimension callouts. The size band is said in words under the drawing — “2.1 m, seats eight” — because a measured drawing would be a promise about a piece that has not been designed yet. A stylised elevation is honest about being an illustration.
Colour
Workshop dusk, and the discipline on the honey
This is the only dark page in its wave, and the brief for it was workshop dusk rather than restaurant velvet: a dark page that reads like the end of a day in a shed with the lights on, not a luxury brand. The honey is the CTA and the price figure and nothing else — never a large ground — because the moment an accent becomes a background it stops meaning “press this”. Every pair below was measured by the wave’s sweep, which this build extended: 166 declared pairs, 0 failures.
The selected chip’s sub-label is the ground colour at 86 % over honey — blended #35291C, 5.39:1. That opacity is a floor, not a preference: the equivalent pair was the colour defect in the previous wave.
Type
A book face for a considered purchase
Newsreader 500/600 carries the headings. It is a book face, and a dining table is a book-length decision — a display sans would have made a $4,300 commission look like a sale. It is used at one deliberately large size in one place only: the piece name above its own drawn elevation, set at 29–30 px directly on top of the drawing so the name and the thing read as one object. That is the page’s single typographic move.
Inter 400/500/600 does everything else, including all figures. Prices are set in the sans on purpose: a figure in a serif reads as an opinion, a figure in a grotesque reads as a fact, and the whole argument of the page is that the figure is a fact you are allowed to see before you ring.
Body is 17 px at 375 and stays there — this trade’s customer is frequently reading on a phone in a lounge room while looking at the space the table has to go in.
Process
Three passes, each one driving the page
Every pass ran against the real page in headless Chrome on its own port: the enquiry form submitted empty and then filled, the estimate walked across the rest state, both swept extrema and seven more vectors, and the state probe read back and asserted against the arithmetic check. Fifty-eight assertions, all green at the end.
Pass 1 — Craft
- The phone field’s pattern threw an exception every time it was checked. [0-9 ()+\-]{8,} is illegal inside a modern v-mode character class — the brackets need escaping and \- is not allowed — so checkValidity() raised a SyntaxError and the pattern never rejected anything. Silent in normal use. Fixed, and now asserted by feeding the field junk and requiring it to be refused.
- The bottom 43 px of the estimate card fell outside the preview frame at 1200 wide, cutting the lead time and the note off the collection’s thumbnail. The desktop rhythm was trimmed — card padding, fieldset margins, chip height, the figure size, and a crop of the elevation’s viewBox — until the whole result block ends at 739 of 750.
- The desk read as a broken L: the pedestal had a foot only at its far right. Redrawn as two drawer fronts over a recessed plinth. The sideboard’s door gaps were three units of black and its top had no overhang; gaps cut to 1.8, overhang added.
- Grain ran horizontally down the legs. It now runs along the length of each part, which is how the board is cut. Grain and cathedral opacities were pulled back from 0.34–0.74 to 0.22–0.52 — the first cut read as stripes, not timber.
- Both hero buttons wrapped to two lines at 375. They now stack full width below 520 and sit side by side above it.
Pass 2 — Depth
- Added the line that costs the workshop money. Under the result, the other two timbers are priced against the one you picked: “Blackbutt is $210 less. Jarrah is $520 more and a week slower.” Every delta is a difference of two licensed cells, and the build sweeps all 45 vectors to prove the sentence matches the model on every one of them.
- Added the maker’s mark — a stamped H over a date rule, low on the left upright, at half opacity. It is the second read, and it makes the trust line at the top of the page literally true of the drawing.
- Added the joinery at full opacity: through-tenons and draw-bore pins, handles, drawer pulls, rail bolts, a headboard groove. Full opacity so they are declared marks (3.48:1 on marri, 5.95:1 on jarrah, 5.57:1 reversed on blackbutt) rather than texture that happens to carry information.
- Added wandering glue lines, and made the grain seed carry the size as well as the piece and the timber — so changing the size band re-lays the boards, the way a maker would.
Pass 3 — Hardening
- Removed one ornament. The hero eyebrow read “COMMISSIONED SOLID TIMBER · BAYSWATER”, directly under a wordmark that already says “Furniture · Bayswater” and directly above a headline that says “made in Bayswater”. Three Bayswaters inside 200 px. The eyebrow went.
- A screen reader heard the price twice. The result card carried a live region and so did the visually-hidden status line that describes the same change. The one on the card was removed and the fuller sentence kept.
- The skip link was invisible even when focused — the classic version of the bug. It now appears as a honey chip at the top left on :focus-visible. Sixteen tab stops were then driven with real key events and the computed outline read at each one.
- Two colours had been minted without being swept: the CTA hover and the dark-button hover inside the honey band. Both were added to the wave’s contrast sweep along with the blended grain texture at both its extremes and the maker’s mark. Re-run: 166 declared pairs, 0 failures, and the numbers in this guide come from that run rather than from the one that prompted it.
- Checked at 375, 768 and 1440: nothing crosses the viewport box, the sticky bar carries a real tel: link and an in-page form anchor, every tap target clears 40 px, and there are no console errors on either page at any width or under reduced motion.
Honesty
What this page declined to publish
The rule for the whole collection is that a figure we cannot stand behind does not go on the page and does not get softened either — it gets declined, and the decline gets written down here.
- No timber certification, grading or provenance claim. A small workshop buys from a merchant and can only repeat what it was told. The page says exactly that, and offers the thing it can actually do instead: show you the boards for your piece before they are cut.
- No hardness, density or movement figure for marri, jarrah or blackbutt. Those are published values and this page is not the place to repeat them second-hand. The three timbers are described by how they behave and what they cost, which is what the decision turns on anyway.
- No deposit figure. The page says a third, as a mechanism, and says when it is due and what it buys. A third of a midpoint would be a new price, and the arithmetic licence for this build defines prices, ranges and lead times — not derived amounts — so it is not printed.
- No delivery price by suburb below the $3,000 threshold, and no country freight figure. Both are quoted at what they cost on the day.
- No structured data about the business. Both pages emit only WebPage, CreativeWork and a breadcrumb, each naming this as a demonstration. Fictional LocalBusiness or Review markup in a real search index is dishonest markup, so the reviews here are plainly labelled demonstration copy and are not marked up at all. What we would ship for a real client is below, as a sample.
Sample only — never live on this page
Local SEO we’d implement for the real business
For an actual Bayswater workshop, the structured data below would ship with real values, alongside a claimed Google Business Profile in the Furniture manufacturer and Custom furniture categories, the same name, address and phone rendered identically on the page and in every directory, and the workshop’s own photos in the profile rather than the drawn elevations.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"@id": "https://example.com.au/#workshop",
"name": "…",
"description": "Commissioned solid-timber furniture …",
"url": "https://example.com.au/",
"telephone": "+61 8 …",
"priceRange": "$$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "… Railway Parade",
"addressLocality": "Bayswater",
"addressRegion": "WA",
"postalCode": "6053",
"addressCountry": "AU"
},
"geo": { "@type": "GeoCoordinates", "latitude": …, "longitude": … },
"openingHoursSpecification": [
{ "@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday"],
"opens": "07:00", "closes": "16:00" }
],
"areaServed": [
{ "@type": "City", "name": "Perth" },
{ "@type": "AdministrativeArea", "name": "Perth metropolitan area" }
],
"makesOffer": [
{ "@type": "Offer",
"itemOffered": { "@type": "Product", "name": "Commissioned dining table" },
"priceSpecification": {
"@type": "PriceSpecification",
"minPrice": 3040, "priceCurrency": "AUD" } }
],
"aggregateRating": {
"@type": "AggregateRating",
// real, verified review data only — never invented
"ratingValue": "…", "reviewCount": "…"
}
}
</script>
Plus the boring, high-yield work that actually moves a local workshop: one page per piece type with its own price anchor and lead time, the suburb list as real internal links rather than a decorative list, image alt text that names the timber and the piece, and a review request sent at delivery rather than at invoice.
Handover
What would change for the real client
- Their photography replaces the drawn elevations. A maker with 210 commissions has a hard drive full of finished tables in real rooms, and one of those beats any illustration. The estimate keeps its controls, its range and its lead time; the panel beside it becomes a photo of the nearest piece they have actually built, and the drawn elevation stays as the fallback for a piece they have not photographed yet.
- Quotes and deposits run through Xero. The enquiry lands as a draft contact, the fixed price goes out as a Xero quote, acceptance triggers the deposit invoice for the third, and the balance invoice is raised on delivery — so the maker never types a price twice and never chases a deposit by text message.
- The workshop visit becomes a real booking. The form is replaced by a slot picker over the maker’s own calendar, with the weekday-evening and Saturday-morning slots that actually suit this customer, and a reminder the day before with the three things to bring.
- The price model moves out of the page. The base figures, the timber multipliers and the lead times become a small config the maker can edit when the timber merchant’s price moves, and the check that proves the model is monotonic runs on every change.
- Reviews come from the profile. The demonstration copy here is replaced by the workshop’s real Google reviews, pulled in, and only then is review markup honest enough to ship.