VOLT: a free, open-source padel & squash club booking template

Stanislav TyshchenkoEngineeringAnnouncement10 min readSep 20, 2026
The VOLT padel template shown on a laptop and phone on a club bench, beside padel balls and a racket

Most padel clubs I look at have the same website: a decent-looking homepage, a photo gallery, opening hours, and a button that says Book on Playtomic. Click it and you leave the club's site entirely. The club spent money on a brand and then handed the only page that makes money to someone else's app.

VOLT is the alternative, and it's free. It's a complete padel and squash club website — court booking grid, coach-led training, checkout, player accounts — that you deploy on your own domain and own outright. The code is MIT licensed and lives on GitHub. The booking engine behind it runs on Opencals, so you're not writing an availability solver or handling card payments yourself.

VOLT homepage hero — "Own the court" over a floodlit padel court, with 17 pro courts and a next-free-court chip

The demo club is a fictional seventeen-court venue in Madrid with four coaches. Every name, price and photo in it is config you replace.

VOLT is a frontend you own (MIT-licensed Next.js 15) on top of a backend you don't have to run (the Opencals Storefront API). Two booking surfaces over one store: a court grid for rentals, a coach-led flow for lessons. Live demo at template-volt.vercel.app.

A court is not an appointment

This is the part that made VOLT worth building rather than restyling an existing template.

An appointment has a person attached. You pick a stylist, a dentist, a physio, and the system checks that human's calendar. Almost every booking tool on the market is shaped around that assumption, which is why so many of them handle courts badly — you end up faking a "staff member" called Court 4 and hoping nothing downstream notices.

A court has no person. It's an independent unit that one group occupies exclusively for a stretch of time, and booking Court 4 at 18:00 should leave Courts 1 through 17 completely untouched. In Opencals terms that's the Self rule with maxAttendees: 1 — a staffless resource. Trainings in the same store use the Staff rule and carry group capacity, which is where the "4 left" counters come from.

The useful consequence is that order and appointment records read correctly either way. A rental comes through as Padel Court 3 — 90 min. A class comes through as Intermediate Group — with Coach Marta. Nobody has to decode a phantom staff member later.

Seventeen courts on one grid

The court page is the centrepiece and it got most of the design budget.

One grid shows every court and every open slot for a day at once. Courts run down the left, time runs across the top, and you flip a Padel / Squash toggle to change which courts fill the rows. There's no service picker in front of it, no wizard, no "step 1 of 4" — you look at the grid and you can see immediately that Tuesday at 19:00 is gone and 20:30 is wide open.

The VOLT court grid — eleven courts down the left, the afternoon across the top, and a duration popover pricing 30, 60, 90 and 120 minutes on Court 3

Tapping an open cell opens a duration popover on the spot. Hovering a duration highlights the cells it would span on the grid behind it, so you can see what you're about to take before you commit, and a Confirm button is the only thing that actually books. I went back and forth on that: the first version redirected straight to checkout on a single tap, which felt fast until I mis-tapped a cell on a phone and ended up two screens deep in a booking I didn't want.

Where the thirty-minute steps get awkward

Courts in the demo sell in 30-minute steps up to two hours. That sounds like a non-problem and it's the bit that took the longest.

The API gives you slots. What a player wants is a duration. So the grid has to walk each court's row, find runs of consecutive free slots, and compose those into the 30 / 60 / 90 / 120-minute options that are genuinely available from the cell you tapped — then price each one. On Court 3 in the demo that's €15, €30, €45 and €60, and if the court is booked at 19:30 the 90- and 120-minute options simply don't appear for an 18:30 start.

That logic lives in a use-court-grid hook rather than in the page, which is deliberate: it's the piece most people will want to change. Clubs price peak hours differently, cap weekend rentals at 60 minutes, or sell 45-minute squash slots. All of that is one hook, not a rewrite.

Coaching needed its own flow, not a variant

The first attempt tried to run lessons through the same grid. It was bad. A player booking a court is scanning for a gap; a player booking a lesson is choosing a coach and a level, and the grid gives them none of that.

So training is a separate surface over the same store. You filter the catalog by sport, format (1-on-1 or group) and level, then book through a classic card-stack: option, coach, date, time, details, payment.

The VOLT training catalog, filtered by sport, format and level, showing padel lessons and group classes with prices

Two things in that flow matter more than they look.

"Any coach" comes first. The coach picker leads with Any coach — next available, ahead of the named ones. A beginner booking their first padel lesson has no opinion about whether they get Diego or Lena, and making them form one is a quiet way to lose the booking.

Group classes show live capacity. A group class is a group service with maxAttendees above one, so every slot carries a real "4 left" count that drops as people book and disappears when it fills.

Training booking — level options, an "Any coach" card beside three named coaches, a date strip and morning slots each showing 4 left

Checkout runs on Stripe Elements with add-ons — racket and ball rental in the demo — and custom questions you configure in the dashboard rather than in the template. Sign-in is passwordless by default: a six-digit code by email, with a password fallback. Every link Opencals emails a player afterwards resolves through a /link/[token] route that signs them in and drops them on the right page.

An evening, and what that actually bought

VOLT went from nothing to the site in these screenshots in one evening. I want to be precise about why, because "we built a booking site in an evening" is the kind of claim that's useless without its conditions.

Three things already existed. The Storefront SDK was at v0.3.14 and typed, so availability, cart, checkout and accounts were calls rather than problems. Three templates had already been built on it — Haar for a salon, Frisor for a barbershop, Clarity for a clinic — so the account pages, auth routes and checkout steps were patterns I'd already argued with. And a seeded demo store meant there were real courts, coaches, prices and photos to build against from the first minute.

What actually took the evening was the court grid, the duration composition, and the dark technical look. The rest was assembly.

The stack is deliberately dull so it's easy to read:

LayerWhat it uses
FrameworkNext.js 15 (App Router)
StylingTailwind CSS v4, design tokens in globals.css
AnimationFramer Motion
Formsreact-hook-form + Zod
PaymentsStripe Elements
AuthNextAuth.js v5, passwordless by default
Datesmoment-timezone
Booking dataOpencals Storefront SDK v0.3.14

Per-page metadata, Open Graph cards, SportsActivityLocation structured data, robots.txt and sitemap.xml ship configured, which is the week of SEO plumbing every club site otherwise pays for.

What it won't do

Four limits, stated plainly, because you'll hit them in week one otherwise.

No waitlist. If Tuesday 19:00 is full, the grid shows it as booked and that's the end of the interaction. For a club, 19:00 on a Tuesday is exactly the slot you'd want a waitlist on. It's the gap I'd most like to close.

No player matching. Playtomic's real product is a network of players who find each other — open matches, levels, results. VOLT has none of that, and neither does Opencals. If your members book because the app finds them a fourth, a template won't replace it.

Opencals itself is not open source. VOLT is MIT and so is the SDK. The platform behind them is a commercial hosted product with a public API, and the engine isn't going to be open-sourced. Clone the frontend freely; the backend is a service you pay for — $14.98/month covering 300 bookings and $0.20 each after that, which is the plan a club doing court volume wants.

The free tier can't take real money. A Dev Store runs in test mode. It's there so you can build and demo the whole thing end to end without a card, and you move to a live store when you want real bookings.

Playtomic solves a different problem

Worth saying clearly, because VOLT's grid is openly modelled on the one padel players already know: Playtomic is good at what it does, and what it does is run a marketplace. Its own pricing page lists four club tiers — Standard, Professional, Champion and Master — with no published prices on any of them, and API integrations only appear from the Champion tier upward (checked 20 September 2026). Players booking through the app pay Playtomic a service fee that varies by country and currency and isn't refunded if they cancel.

If most of your bookings arrive from players discovering you inside that app, that's a real distribution channel and a template is not a substitute for it. If most of your bookings are your own members, who already know your name and are going through a third-party app to reach you, the trade looks different. I've written that comparison out properly — including the arithmetic — rather than squeezing it in here.

The parts you'll edit first

Two files carry almost all the club-specific work.

lib/site-config.ts holds every piece of copy — club name, tagline, the two sports and their price hints, hero text, coaches, gallery, stats, testimonials, FAQs, address, hours, footer and social links. Rebranding the site is editing that one file. The bookable data — courts, trainings, prices, availability — comes from your Opencals store, not from the repo.

app/globals.css holds the design tokens as Tailwind v4 @theme properties. Token names are stable on purpose, so components keep working when the values change:

css
@theme { --color-bg: #0A0A0A; /* near-black page background */ --color-primary: #FF4A1C; /* electric-orange accent */ --font-display: 'JetBrains Mono', ui-monospace, monospace; }

Swap the orange for your club's colour, change the display face, and the site follows. Keep that accent matched to your storefront primary colour in Opencals so the booking emails don't clash with the site. One nice touch if you have footage: drop a file at public/videos/hero.mp4 and the homepage hero upgrades from a still to a looping video with no code change.

Getting it onto your own domain

You don't need to clone anything locally to get a live site.

1

Create a Dev Store and seed it

Sign up at app.opencals.com, create a Dev Store, and choose the VOLT Padel & Squash preset when it asks for a dataset. That seeds the courts, coaches, training classes, add-ons and venue the template expects, so your site renders like the demo instead of empty.

2

Generate a Storefront API key

In your Opencals account settings, generate a Storefront API key. It starts with sfk_ and is scoped to that one store.

3

Deploy to Vercel

Use the deploy button below. Vercel asks for OPENCALS_API_KEY and AUTH_SECRET — paste the sfk_ key and any random string. Add a Stripe publishable key when you want to take real payments.

Deploy with Vercel

Do this on day one or your emails break

Set Storefront Base URL in your Opencals dashboard (Settings → API) to your deployed domain. Every player link — view booking, reschedule, cancel, leave feedback — is built as {storefrontBaseUrl}/link/{token}. Leave it pointing at localhost and those links go nowhere.

If you run a club, the question VOLT is really asking is whether the page where your members spend money should be yours or someone else's. If you build for clubs, it's a working reference implementation of court booking on a headless backend — and you can fork it into your own design system in an afternoon. Either way, it's on GitHub and it costs nothing to find out.

Frequently Asked Questions

Early Access — 3 Months Free

Ready to transform your service business?

Join 150+ businesses already using Opencals. Get 3 months completely free with all features unlocked.

No credit card required
Setup in 10 minutes
Cancel anytime