Second SwellBuild guide

Making Second Swell

Second Swell Surf School is a fictional learn-to-surf operator at Trigg and Scarborough, built as a surf-school industry demonstration. The page has one job: a lesson booking with the format, pack and party size already priced — for the parent booking a grom’s first lesson, the adult who keeps watching other people surf, and the mates buying a lesson pack instead of another hoodie.

The Session Board

The signature is a drawn SVG cross-section of the Trigg bank at first light: procedural waves rolling over the sand bank, surfer silhouettes riding the face, and the coaching flag planted on the beach carrying the live price. Every control redraws the scene honestly:

The board pre-fills the booking form with the configured session, so the demo interaction becomes a warmer enquiry — the classic calculator→form handoff.

Honest pricing model

All prices are per surfer for the pack; the total is the per-surfer pack price times the party size, plus photos at $45 per session times the pack’s session count. School programs and corporate days deliberately print no number — headcount pricing is quoted per program, and saying so plainly beats inventing a figure.

FormatSingle3-pack (per surfer)5-pack (per surfer)Surfers
Group · 2 h$75$210 ($70 a lesson)$325 ($65 a lesson)1–4 (stepper)
Semi-private · 90 min$110$300$475locked at 2
Private · 60 min$150$420$650locked at 1
Session photos+$45+$135+$225flat per session

Worked figures verified against an independently reimplemented oracle in the QA harness: rest state group × 2 on the 5-pack = $650; the grid floor group single = $75; semi 3-pack = $600; private 5-pack = $650; rest + photos = $875 with the photo line reading “$225 — 5 sessions”; and the pack-change intersection (group × 2, 3-pack, photos on) = $555 with the photo line re-priced to “$135 — 3 sessions”. All totals display to the whole dollar; every anchor and multiplier is integer-safe.

Palette — argued from the sand, the deep water and the sunrise

Contrast ratios below are measured WCAG figures from the shipped tokens, not estimates.

Morning sand#F4F1E7page ground
Deep-water navy#16323Ebody ink — 11.91:1 on sand
Sunrise coral#C7502Fmarks & large display — 4.55:1 with white, 4.02:1 on sand
Coral button fill#A8401Funder white labels — 6.14:1
Coral text-ink#93381Bcoral-coloured copy — 6.58:1 on sand
Sea glass#6FA294wave linework only — 2.56:1, never type
Glass ink#38635Asea-glass-coloured copy — 5.99:1 on sand

The spec pre-minted the coral two-token pair (button fill + text-ink) because raw coral was hypothesised to land between 4:1 and 5:1 — measurement confirmed it (4.55:1 with white, 4.02:1 on sand), so white-label buttons use #A8401F and coral-coloured small copy uses #93381B. Sea glass measured 2.56:1 and stays strictly a line-and-mark colour, with #38635A as its text ink.

Type

Bricolage Grotesque (700–800) carries the display voice — a salt-crusted grotesque with a wetsuit’s squeak of character, set huge for “STAND UP BY THE THIRD WAVE” over the drawn break. Figtree does the workhorse duty: friendly, legible at 16.5px body size, and happy in a price ledger.

Techniques

Every visual is procedural — no raster images anywhere. The scene is a single SVG whose water surface is rebuilt each animation frame: a skewed gaussian crest (steeper on the shoreward side, so the wave reads as breaking over the bank) summed with two travelling sines, damped to nothing as the water shallows at the shoreline. Surfer silhouettes sample the same surface function at their x-position each frame, so they rise, fall and tilt with the face they’re drawn on. The rAF delta is clamped at zero and capped (dt = min(max(now−last,0)/1000, .05)), the loop pauses when the tab hides, and reduced-motion visitors get a settled mid-roll frame with no loop at all. Wave stroke opacities oscillate but never drop below 0.55, so the signature is visibly alive at any capture instant.

State changes use a dual-speed redraw: the first render earns the full staggered entrance, then every chip tap redraws snappy (~520 ms cap) via a first-draw flag. Each control handler bumps a build token before swapping state, so an in-flight rebuild can never act on stale scene data — rapid-fire chip sequences were driven in QA to prove it. The flag’s price badge lives inside the artwork (the thumbnail is the commercial argument) and swaps to a tight, subtitle-free variant below 480px of scene width so it never covers the drawn wave on a phone.

Conversion decisions

Local SEO we’d implement for the real business

The demo page deliberately ships only WebPage/CreativeWork-family structured data — fictional business schema in a real index would be dishonest markup. For a real surf school we’d ship SportsActivityLocation — the organization subtype that actually matches a surf school (more precise than bare LocalBusiness, and the type Google’s own docs use for sports venues and activity providers) — plus a genuine review feed:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "SportsActivityLocation",
  "name": "Second Swell Surf School",
  "description": "Learn-to-surf lessons at Trigg and Scarborough —
    group, semi-private and private coaching, boards and
    wetsuits included.",
  "url": "https://secondswell.com.au",
  "telephone": "+61 8 9000 0332",
  "priceRange": "$75–$650",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Trigg",
    "addressRegion": "WA",
    "postalCode": "6029",
    "addressCountry": "AU"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": -31.867, "longitude": 115.753 },
  "areaServed": ["Trigg", "Scarborough", "North Beach", "Karrinyup", "Doubleview"],
  "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],
    "opens": "06:00", "closes": "13:00"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.9", "reviewCount": "187"
  },
  "review": {
    "@type": "Review",
    "reviewRating": { "@type": "Rating", "ratingValue": "5" },
    "author": { "@type": "Person", "name": "A real customer" },
    "reviewBody": "Real review text, streamed from the Google
      Business Profile — never invented."
  }
}
</script>

Alongside the schema: a Google Business Profile tuned for “surf lessons Trigg / Scarborough / Perth northern beaches”, suburb-level landing content for the beaches actually taught, and FAQ markup for the questions the car park actually asks.

What changes for the real client

Iteration log

Pass 1 — Craft

Measured every spec contrast hypothesis: navy 11.91:1, coral/white 4.55:1, button fill 6.14:1, coral text-ink 6.58:1, glass-ink 5.99:1 — the pre-minted two-token coral pair confirmed necessary (raw coral is 4.02:1 on sand, marks and large display only). The first scene render failed the screenshot review: the sand profile was pinned too deep, so the water read as a dark wall instead of a first-light surf band, and the symmetric crest read as a hill with surfers standing on top. Raised the sand profile so the water is a shallowing band, lightened the sea gradient, skewed the crest steep-side-shoreward, moved the foam onto the breaking face, scaled the silhouettes up ~35% and deepened the bank hump so “THE BANK” label points at something real.

Pass 2 — Depth

Tightened the crest breathe range (0.93 ± 0.07) so the wave face is visibly mid-roll at any capture instant, not just at lucky phases. Added the tally gate — the 5-pack’s fifth notch strikes diagonally through the four, the way anyone actually counts — drifting gulls that wrap the sky, and a tilt clamp so surfers lean into the face without cartwheeling. Micro-interaction: the session total pulses once on every honest re-price. Repositioned the photographer onto the beach slope beside the flag, clear of the tally notches.

Pass 3 — Hardening

Native-resolution 375px review, masthead first: wordmark clears the call link with room to spare (the “surf school” descriptor drops below 400px), and the badge’s tight variant (price only, 116×44 in scene units) verified active so it never covers the drawn wave. Label-collision sweep at native resolution across scene states: badge vs display type, pennant vs notches, photographer vs flag, “THE BANK” vs sand edge — clean. Drove every control plus two rapid-fire sequences (no settle between clicks) against the independent pricing oracle: 60+ asserts green, zero console errors, forced stepper states and the whole-bank note (present at four, absent at three) verified both ways. Reduced-motion path renders the settled mid-roll frame with no animation loop. Chanel rule: removed the badge’s leader line to the flag pole — the badge’s position already says it.

Colophon

Second Swell Surf School is a fictional business — a surf school industry demonstration designed & built by Sapience Analytics, part of the Generative Assets collection. Phone numbers use the reserved (08) 9000 0xxx pattern; ABN and Working With Children numbers are visibly placeholder-patterned.