All work

2026, live at clubhive.app

ClubHive

Event booking for community clubs — run clubs, cycling clubs, walking groups. Organisers post events and embed a booking widget on their own website; attendees RSVP with no account needed. The booking is the front door. The community is the value.

  • Next.js
  • Neon
  • Drizzle
  • Better Auth
  • Resend

Update, October 2026: ClubHive is live

The cycling club below is Bells Angels. Their site now pulls its rides, club news and photo gallery from ClubHive's public API, so the committee edits one dashboard and the website keeps itself current; ride bookings move over next. Since then other clubs have signed up, and the platform has grown a public events map, a gallery on Cloudflare R2, a blog editor, reminder emails and a privacy self-service flow. See its live status.

The problem

Small clubs run their events through a patchwork of WhatsApp polls, Google Forms, and Facebook events. Nobody knows how many are coming until they turn up. The tools that do solve booking — Eventbrite and friends — are built for one-off ticketed events: heavy, fee-laden, and they keep the attendee relationship for themselves.

I saw this first-hand building a website for a cycling club in my freelance practice. The site looked the part, but the moment someone wanted to actually join a ride, the experience fell off a cliff into a group chat. The club also had no memory: no record of who came back week after week, or who drifted away.

The idea

ClubHive treats every RSVP as the start of a relationship, not a transaction. Each booking builds the club's own attendee ledger — who's new, who's loyal, who's lapsed — and when the next event goes live, the club can reach all of them directly. Organisers get a lightweight CRM they never had to fill in; attendees get a one-tap RSVP and never see a password field.

My role

Solo build — product design, data model, and implementation. The project is also a deliberate exercise in the modern serverless Postgres stack: Neon's database branching for environments, Drizzle for end-to-end type safety, and Better Auth's organisations plugin doing the multi-tenancy heavy lifting.

Architecture

Frontend

Framework
Next.js App Router · TypeScript
UI
Tailwind CSS · shadcn/ui — mobile-first
Embed
Stripped-down iframe booking widget
Theming
Widget inherits the club's brand colour
Hosting
Vercel

Data

Database
Neon — serverless Postgres
ORM
Drizzle — type-safe, Neon-native driver
Environments
Neon branching for dev / staging
Model
Clubs → events → bookings → attendees
Attendees
One record per person per club

Platform

Auth
Better Auth — organisers only
Multi-tenancy
Organisations plugin maps to clubs
Email
Resend — confirmations & announcements
Payments
Architected for Stripe — not in MVP
Live spots
Polling now, websockets later

Key decisions

Open any decision to see the situation and what I did about it.
  • The situation

    The audience is someone deciding on a Tuesday night whether to join Sunday's ride. Any sign-up wall at that moment costs the club the booking — and small clubs can't afford to lose a single one.

    What I did

    RSVP is a name, an email, and a tap. Every booking carries a unique token; the confirmation email includes a cancel link keyed to it. Attendees get full control of their booking without ever seeing a password field.

  • The situation

    Clubs are textbook tenants: owned by an organiser, possibly co-administered later, with every event and attendee scoped underneath. Building that scoping by hand is where solo projects leak data.

    What I did

    The organisations plugin maps one-to-one onto clubs, so membership, ownership, and future co-admin invites ride on a maintained auth layer. Tenant scoping lives in one place instead of being re-implemented per query.

  • The situation

    A person who rides with two clubs is two different community members. A global attendee profile would leak one club's audience to another and make consent murky — whose mailing list are they on?

    What I did

    One attendee record per person per club, accumulated across bookings. Each club owns its list outright: events attended, first seen, last seen, marketing consent. Privacy boundary and CRM in the same design move.

  • The situation

    Clubs already have websites they're proud of — often built by a local freelancer. Asking them to send members to a third-party platform breaks their brand and hands their audience to someone else.

    What I did

    The booking form ships as a single iframe snippet that inherits the club's brand colour and looks native on the host site. The club's website stays the front door; ClubHive is the machinery behind it.

  • The situation

    Booking data is exactly the kind of state you don't want to test against in production, but maintaining a separate seeded staging database is busywork for a solo builder.

    What I did

    Every feature branch gets a database branch — production-shaped data, isolated writes, deleted when merged. Schema migrations via Drizzle run against the branch before they ever touch production.

Technical depth

The embed widget

The widget is the product's distribution strategy. It's a stripped-down route rendered inside an iframe — no nav, no marketing, just the next events and an RSVP form. The club sets a single brand colour at creation, and the widget derives its entire theme from it, so the embed reads as part of the host site rather than a third-party bolt-on. Live spots remaining update by polling — simple and sufficient at this scale, with a clean upgrade path to websockets.

Club brand colour

One colour, set once when the club is created. The widget derives its whole theme from it — buttons, capacity bar, confirmation state.

Embed snippet
<iframe
  src="clubhive.app/embed/sunday-riders"
  width="100%" height="480"
/>

Paste it once and it works on any site.

SRSunday Riders CC
Sunday Social — 40km
Sun 21 Jun · 09:00 · Village Hall car park
23 of 30 spots taken7 left
Powered by ClubHive

Live demo, as it would sit on the club's own site

Try it: pick a club colour, then RSVP.

The attendee ledger

Every booking is written against a per-club attendee record — one row per person per club, accumulated across events. From that single table the club gets its community picture for free: first-timers, regulars worth flagging (3+ events), and lapsed members who haven't been seen in 60 days. When a new event is published, everyone who gave consent hears about it — the attendee effectively subscribed to the club the moment they first booked.

E1E2E3E4E5E6Status
A01Loyal
A02Loyal
A03Lapsed
A04Loyal
A05Lapsed
A06Loyal
A07—
A08Loyal
A09—
A10Loyal
A11—
A12—
First booking Came back
31 bookings · 12 people · 6 loyal · 2 lapsed
Twelve attendees across six events, and what the ledger makes of them.

Capacity and the waitlist

Capacity is enforced in the database, not the UI. A booking insert runs in a transaction that counts confirmed bookings with the event row locked — two people grabbing the last spot can't both succeed; the second lands on the waitlist with its own confirmation email. Cancellations promote the head of the waitlist automatically, and the cancel link in every email means the whole lifecycle works without a login.

Design goals

0

accounts needed to RSVP

0

snippet to embed anywhere

100%

of the audience owned by the club

3+

events attended flags a loyal member

Where it goes next

The MVP is deliberately narrow: clubs, events, bookings, emails, embed. The growth direction is the community layer — event announcements to past attendees, engagement insights (which events pull the best turnout, who came once and never returned), and recurring events for the weekly ride. Stripe lands when paid events do; the schema is already shaped for it.

Further out: white-label embeds with custom domains — aimed at freelancers and agencies who want to bundle bookings into the club websites they already build. That loop closing is the long game: the product was born inside a freelance club-site build, and it goes back out through them.

Need a site that does more than sit there?

Tell me a little about your club, business or idea. I'll reply personally — no sales team, no forms, just a conversation about what you need.

Email me
Alexander Dean, web developer in the UK. It's --:-- here.