Why this converts
The question a parent asks before loading the car is answered beside the headline on a laptop and one scroll down on a phone, while the phone number and “Book a group morning” stay in the header and a call bar sits under the thumb.
The board says “Closed — picked out, don’t drive out” on the days it is, which costs the farm a Sunday visit and buys the trust that makes every “Open” on the board believable.
The visit check prints the shop’s pre-picked price beside the pick-your-own total in every state and says plainly when the shop is $6 cheaper, so the dearer outing reads as chosen rather than sold.
The form asks only what a group booking needs (who, a phone number, what kind of group, how many children and which weekday), and it turns away a Saturday school group or a 12-child excursion with the right alternative before anyone has to ring.
Trust comes from specifics a family can check on the day: a board updated by 7am, the price of a tray, under-4s free, and tap and cash at the gate.
Palette
The berry and the crown it hangs from, on the pale green light inside a tunnel. Not cream, not terracotta. Ratios for the declared tokens are pasted from contrast-w60.log; the colours minted during the build were measured with the same formula and are listed with the only job they are allowed to do.
Also minted, each decorative or state-only: button hover #8A1831 (white on it 9.31:1), hero wash #F7F9F3 (ink 16.29:1, muted 8.08:1, primary 7.19:1), second leaf #6E9A48 (2.99:1 on bg, leaves only), Thursday rain #8A9AA5 (2.90:1 on surface), hairline #D8DFCC (1.37:1) and map road #C8BEAC (1.84:1), lines that carry no information of their own.
Type
Bree Serif
Headings, the day names on the board and both visit figures. It is a friendly slab with the look of a painted farm-gate sign, sturdy enough to read at 15 px on a board tile.
Nunito 400 and 700
Body, the steppers, the status line and every small figure. Its rounded terminals match the slab without going childish, and it holds up at 11 px on the phone board.
The proof element: this week at the farm
Three parts in one card. A seven-day board, labelled as a demo week, where each day reads Open 8–12, Open 8–4, Closed — picked out, or Open, tunnels covered (rain); tapping a day rewrites the status line, the tunnel labels and the drawing, and arrow keys move through the week. Below it, a cross-section of the four tunnels drawn once in SVG at load: arched covers, two raised troughs a tunnel on legs, leaves, and ten berry slots a tunnel that are ripe or green according to that day’s fruit level. Open tunnels get a solid leaf-green hoop and resting ones a dashed pale hoop. On Thursday rain falls on the covers, driven by the wall clock, paused when the tab is hidden, and never started under reduced motion.
Last, a visit check with four steppers (adults, children 4+, under-4s, trays). Entry is $3 for everyone aged 4 and up, a pick-your-own tray is $16, and a pre-picked shop tray is $19 with no entry. window.__farmgate exposes the selected day, the four inputs, entry, trays, total, the shop figure, the difference, which is cheaper, isSubstitute and its reason, the open tunnels, the drawn berry count and the form state. The page’s model block was checked in node against the wave’s figures script on all 63,700 reachable cells (7 days × 10 × 13 × 7 × 10), with 0 disagreeing.
| Worked example (figures-w60.mjs) | Entry | Trays | Pick your own | Shop instead |
|---|---|---|---|---|
| 2 adults, 2 children 4+, 1 under 4, 2 trays (the rest state, Saturday) | $12 | $32 | $44 | $38, $6 less at the shop |
| 2 adults, 3 trays | $6 | $48 | $54 | $57, $3 less picking |
| 1 adult, 1 tray (the grid’s “from”) | $3 | $16 | $19 | $19, the same |
| Group morning, 24 children | 24 × $7 = $168, teachers free | — | ||
Where the page argues against its own sale
Monday and Sunday on the board read “Closed — picked out, don’t drive out”, and on those days the check prices the next open day and turns the shop figure into a pre-order collected at the gate. The shop figure is printed in every state at the same size as the pick-your-own total. When the shop is cheaper the page says so: “If the picking isn’t the point, the shop is quicker and $6 cheaper.” isSubstitute is true only when the shop costs the same or less, the shop is open, and there are no children in the party; with children along it is false with the reason “the shop sells the fruit, not the morning”, and when picking is cheaper it says why (at the shop you pay for the farm’s picking time).
Iteration log
Each pass drove the page in headless Chrome at 375 × 667 and 1200 × 750: the day tiles by click and keyboard, the four steppers to the three worked examples, and the form empty, with junk and filled. Each pass also re-ran the page’s model block in node against the wave’s figures script on all 63,700 reachable cells, with 0 disagreeing.
Pass 1: Craft
- The drawing’s viewBox carried 44 units of empty sky above the tunnels. Cropping it lifted the steppers and pulled the sentence under the two figures inside the 1200 × 750 frame, where before it sat below 750 px.
- At 375 px the eyebrow wrapped to two lines. Under 560 px it now drops “Pick your own”, which the headline already says.
- When picking was cheaper, the sentence ended on the kids running out of steam even for two adults with no children. It now depends on who is in the party.
- The map section’s heading and two labels on the drawn roads named real roads. The heading now names only the locality and the roads are drawn unlabelled.
- At 375 px the map’s home label ran off the right edge; it is now centred above the pin. Three suburbs listed beside the map had no dot and one dot had no listing; the two now match.
- The first harness run expected 17 ripe berries on Saturday. That day’s fruit levels round to 22, the page drew 22, and the harness was corrected rather than the page.
Pass 2: Depth
- Closed days now carry a “Show Tuesday” button in the status line, so “don’t drive out” ends in something to do. Driven from Monday it selects Tuesday, moves focus to the Tuesday tile, rewrites the status to Open 8–12 and hides itself.
- The closed-day status said “don’t drive out” twice in two lines and called picked-out tunnels “resting”. The notes were rewritten, and the text and the drawing now both say picked out.
- Each berry is now a group with a green calyx, a detail seen on the second look, and the calyx scales with its berry as the fruit ripens.
- Thursday’s rain was a sparse row of ticks. It is now three staggered rows at 14-unit spacing, still wall-clock driven: two reads 300 ms apart show it moving, and under reduced motion it stays still.
- The thumbnail state re-read 8 seconds after the 7-second instant was identical, with all 22 ripe berries at full opacity inside the frame.
Pass 3: Hardening
- Day tiles measured about 38 px wide at 375 px, under the 44 px tap floor. Under 420 px the board now wraps to rows of four and three, and the closed-day button grows to 44 px on phones.
- Tunnel labels such as “4 · picked out” nearly touched between tunnels at 375 px and were set a size smaller.
- Every rule that hides something at a breakpoint (
.wide-only,.day .ds,.mast-tel .t,.map .minor) has its match count asserted rather than assumed. - Checked horizontal overflow at 320, 375, 768 and 1440 px on both pages. Arrow keys wrap Sunday to Monday, Home and End jump to the ends of the week, and the focus ring shows on the tile. Junk in the phone field is refused by the script and by the native pattern, which compiles under the
vflag. A Saturday school booking and a 12-child excursion are refused with their alternatives, and 24 children confirm at $168. - Chanel rule: removed the second “Book a group morning” link from the desktop hero note, which sat about 100 px under an identical button. The note keeps the price and the punnet.
Conversion decisions
- The board is the first CTA. “Check today’s board” is the primary hero button because the visitor’s first question is whether to drive, not whether to book. On a laptop the board is already beside the headline.
- The group booking is the conversion. “Book a group morning” sits in the header, the hero, the phone bar (as “Book a group”) and above the form, because a school or playgroup booking is worth fifteen family visits and it is the one that needs a phone call.
- Six form fields, two of them conditional. Number of children and weekday become required only for a school, kindy or playgroup; a pre-order needs a collection day; a family visit is told it does not need to book at all.
- Refusals that redirect. A Saturday school booking is refused with “Group mornings run Tuesday to Friday”, and a group of 12 is pointed at an ordinary open morning at $3 a head rather than simply rejected.
- A confirmation that repeats the price. A 24-child request confirms “24 children at $7 is $168”, teachers free, one punnet a child, and says plainly that nothing was sent because this is a demonstration.
Market band
Perth Is OK lists a Bullsbrook pick-your-own farm charging $15 a tray plus $2 entry. Tunnel Row’s $16 tray and $3 entry sit just above it, argued by the covered tunnels.
What this page declined to publish
- No food-business registration, exemption or food-safety claim, and nothing about how the fruit is grown: no spray-free, organic or chemical-free wording anywhere.
- No WA strawberry industry figure and no season claim beyond the farm’s own “late August to December, weather willing”.
- No real farm named on the site, no street or road name as a location, and no drive times: the map rings are straight-line distance and say so.
- No regulation behind the dog rule; it is stated as the farm’s own rule, with assistance dogs welcome.
Local SEO we would implement for the real business
The live page carries only a WebPage block naming it a demonstration, because structured data about a fictional farm in a real index is dishonest markup. For the real farm we would ship the block below with their verified details, their season as dated opening hours, and reviews pulled from a real source.
{
"@context": "https://schema.org",
"@type": ["LocalBusiness", "TouristAttraction"],
"name": "[Farm name]",
"url": "https://[their-domain]/",
"telephone": "+61 8 0000 0000",
"priceRange": "$3 entry, $16 a tray",
"address": {
"@type": "PostalAddress",
"streetAddress": "[street address]",
"addressLocality": "Carabooda",
"addressRegion": "WA",
"postalCode": "6033",
"addressCountry": "AU"
},
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"opens": "08:00", "closes": "12:00",
"validFrom": "[season start]", "validThrough": "[season end]"
}],
"makesOffer": [{
"@type": "Offer",
"name": "Group morning",
"priceSpecification": { "@type": "UnitPriceSpecification", "price": 7, "priceCurrency": "AUD", "unitText": "per child, 15 children minimum" }
}],
"review": [{
"@type": "Review",
"author": { "@type": "Person", "name": "[Verified reviewer]" },
"reviewRating": { "@type": "Rating", "ratingValue": 5, "bestRating": 5 },
"reviewBody": "[Review text from their Google Business Profile]"
}]
}
Also for the real farm: a Google Business Profile with its seasonal hours kept current, and the day’s status posted as a Google Business Profile update, so the profile says the same thing as the board.
What changes for the real client
- A board the farmer can update from the paddock. The seven-day board reads a Google Sheet the family edits on a phone at 7am, or the day’s tray stock from their Square or Shopify point-of-sale, so “picked out” appears the moment the shop sells its last tray.
- One update, three places. The same 7am update posts to Instagram and Facebook automatically through Make.com or n8n, so the page, the socials and the Google profile never disagree.
- Group bookings in a booking tool. Group mornings move into Bookeo or Calendly with real weekday slots and a capacity of one group a tunnel, and the confirmation sends the school a tax invoice.
- Their own proof. Photographs of their tunnels beside the drawing, their season dates, and reviews from their Google Business Profile in place of the demo copy.