Skip to content
Point Break Surf AcademyConcept build2026

A one-page booking site with a real pricing engine, no backend

Point Break is our concept build for a surf school in Jeffreys Bay: lessons, camps, coaches and a live custom-quote calculator, all on one scrolling page, all running client-side with zero framework and a 331ms LCP on the live URL.

Snapshot

Client
Point Break Surf Academy — a GoodGround concept brand
Industry
Adventure travel and sports coaching, direct to consumer
Services
Design, front-end build, booking UX, SEO setup
Build
Hand-written HTML, CSS and JavaScript. No framework, no build step, no backend.

The challenge

Most one-page booking sites pick one of two failure modes. Either they are a brochure page that funnels every enquiry through a single generic contact form, hiding the real detail — durations, group sizes, what's included, day-by-day itineraries — behind a phone call. Or they try to be a genuine booking engine and end up needing a backend, a database and a payment processor before the first lesson is ever listed.

We set the brief to prove a middle path. Four different kinds of bookable content — three lesson tiers, three camp packages, four coaches, and a fully custom package — needed to sit on one scrolling page, each with real depth behind a click, and a price calculator that had to feel like it was talking to a live pricing API when it was actually running entirely in the visitor's browser.

The solution

One modal pattern doing four different jobs

Lesson details, camp itineraries, coach bios and the booking form all open in the same modal shell: an image header, a scrollable body, and identical close behaviour on the X, a click outside, or Escape. The content inside is entirely data-driven, so the shell was built once and every card on the page just feeds it different data.

The booking modal specifically can be opened from several places across the page — the hero, the sticky nav, the floating button, inside a lesson or camp's own detail modal, or the package builder — and pre-fills itself with whatever package and price the visitor was already looking at.

The coach bio modal open on the live site, showing a founder's background and coaching philosophy

A price calculator with nothing to talk to

The package builder recalculates a full ZAR quote — lesson tier, camp package, add-ons, guest count — the instant any selection changes, entirely with client-side JavaScript. There is no API call, no debounce waiting on a network response, because there is no network response to wait on.

Every line in the breakdown is generated from the same selection state that produces the total, so the two can never drift out of sync with each other, which is the failure mode that makes most DIY quote widgets untrustworthy.

The Build Your Trip package builder mid-selection, showing a live R45,200 total with an itemised breakdown

Pricing tiers that read like tiers, not a template

The three lesson cards and three camp cards are the same shape by necessity, since they are directly comparable pricing tiers, but each one carries its own photograph, specific inclusions and a list of real outcomes, rather than the generic icon-plus-heading treatment that makes most pricing sections look interchangeable.

The distinction matters most in the details a visitor actually compares before booking: group size, duration, and what happens in the lesson, not just the price.

The three lesson tier cards, Beginner through Advanced, each with its own photo, price and outcomes

Built mobile-first, because that is how it gets booked

Most bookings for a trip like this happen from a phone, often while travelling, so the layout was designed at 390px first and worked up, not scaled down from a desktop comp. Every card grid, the package builder's two-column layout, and all four modals were checked at 320px, 768px and 1920px with zero horizontal overflow at any of them.

The one CSS bug worth naming: a `<select>` with long option text can force a grid track past its container's width unless the track is explicitly clamped with `minmax(0, …)`. It shipped, was caught in testing, and is now the reason every grid on the page that hosts a form control uses that pattern.

The Point Break hero rendered on a 390px-wide phone screen with no layout overflow

The results

Every figure below was measured on the live URL. Each one tells you how to check it yourself.

331 ms

Largest Contentful Paint

Record a performance trace against the live URL in Chrome DevTools.

0.00

Cumulative Layout Shift

Same trace, same run.

100

Lighthouse Accessibility

Run Lighthouse against the live URL in Chrome DevTools.

100

Lighthouse Agentic Browsing

Same audit, same run.

5 files

Entire site

View source on the live URL: one HTML file, one stylesheet, one script, robots.txt and sitemap.xml. No bundler output.

0

Console errors

Open the Console on the live URL.

Point Break Surf Academy is a fictional brand with no customers, so like B3TTER, there is no traffic, bookings or revenue to report, and the six testimonials on the page are invented and disclosed as such in the footer. The site also carries a deliberate noindex tag and a Disallow in robots.txt, which is why its own Lighthouse SEO score reads around 66 rather than 100: a made-up surf school has no business ranking in real search results. Every other SEO check on the page passes, and removing those two lines is a one-line change if this pattern is ever reused for a real client.

Want a website like this?

Tell us what you sell and who you sell it to. We will tell you honestly whether a new site is the thing that will move the needle.