Self-initiated product · design, code and operations

The Social Hub

The Event Platform that changes everything

In 2014, while having a shower in my Frankfurt apartment, I had the amazing idea of a platform in which users could post any type of event for free to meet new people. I'm talking about an era pre-Meetup. My idea from the beginning was minimum and maximum attendees for activities. Since today, no other platform has created such a concept. I tried two times to roll out this project, but I always failed at getting investors to develop such a platform. After many years and my newly acquired superpowers in AI development, I just went for it as a solopreneur, and this is how I did it.

For
Anyone who has moved city, changed jobs, or run out of friends who are free on a Saturday.
Role
Everything — product, design system, frontend, backend, database, payments, deployment.
Why
A private project to force myself through an unfamiliar stack end to end, with a real product as the exam.
Status
Live at joinsocialhub.app · bilingual · demo seed data before launch.
The Social Hub home page on a laptop: German hero headline, search bar and tilted event cards showing how many people are still missing
The same home page on a phone, with a condensed hero and stacked search fields

Because you cannot play a football match with two people

Some hobbies have a floor. A football match needs about ten people. A board-game night needs four. A language exchange needs at least one person who speaks the other language. Below that number the activity does not get worse — it stops existing. And the people who feel that most are exactly the ones with the least room to fix it: you moved to a new city, or changed jobs, or your old crowd all have kids now, and the three friends you have left are busy on Saturday.

What you need in that moment is not a bigger social network. It is seven more people who also want to play at three o'clock on Saturday, in the same part of town, this week. That is a very specific kind of matchmaking, and almost nobody builds for it — because it is much easier to build a platform where attendance is a number that goes up than one where attendance is a condition that has to be met.

Joining stops being a gamble

Turning up alone to a thing that might not happen is a lot to ask of a stranger. Here you can see whether it is going to happen before you commit — and if it does not, it is cancelled properly instead of quietly shrinking to four awkward people in a park.

Hosting stops being lonely

The host says up front: this only works with ten. From then on everyone who has already said yes has a reason to invite one more person — the countdown is on their evening too. Recruiting stops being one person's unpaid job.

The maybe disappears

Five people say maybe, two turn up, the host stops hosting. That is how hobby groups die. A deadline replaces the maybe with an answer, and a clean cancellation costs a group far less than a disappointing evening.

Thursday · five-a-side

6 of 10 · needs 4 more · closes Wednesday

Thursday · five-a-side

10 of 10 · the match is on

The whole product is that one sentence, taken seriously: a gathering has a minimum crowd, and everybody can see how close it is. Everything else in this case study — the interface, the database, the payments — exists to make that sentence true for a stranger on a phone.

One rule, visible everywhere

The threshold is not a setting buried in a form. It is the interface. A card does not say "3 attending", it says how many people are still missing and how long they have. An event page leads with the same sentence. The progress bar is the product promise rendered in eight pixels of colour, and every state in the system — needs people, almost there, happening, cancelled — is a state a visitor can read at a glance.

Event cards near you, each showing how many more people are needed and a progress bar toward the minimum

Browsing: every card counts down to its minimum

Event detail page with the headline this event still needs nine people to happen, plus date, location and RSVP deadline

Deciding: the event page says exactly what is missing

How it is built

Client and server are one TypeScript project running as one process. The browser calls server procedures directly, so a renamed database field turns into a red squiggle in a React component instead of a runtime surprise in production. There is no separate API contract to keep in sync, because there is no separate API contract.

In the browser React interface
  • One token-driven component system
  • Separate desktop and mobile shells
  • German and English from the same screens
One Node process Hono + tRPC
  • Sessions, email and Google sign-in
  • Payments, built and dormant
  • Housekeeping on an hourly job
Hosted in Frankfurt Postgres
  • Drizzle ORM, nine tables
  • Generated, reviewable migrations
  • Push to main deploys the lot
Shared contracts Thresholds, deadlines and filter logic live in one folder imported by both sides. One implementation, two runtimes — the server can never enforce a rule the interface does not show.

The part I did not expect to matter: I gave a personal project a proper design system, out of habit. It paid for itself the first time the entire mobile experience had to be rebuilt — the rebuild was a layout problem, not a repainting job.

Money I deliberately never hold

Paid events meant deciding where ticket money sits between purchase and event. The comfortable answer is "our account". The correct answer, in Switzerland, is nowhere near it: holding other people's money can count as taking deposits or as financial intermediation, and that is a regulated activity with a regulator attached. So the money never lands anywhere I control.

Step 01 Buyer pays

Charged on the platform account through a hosted card field, so raw card numbers never touch my own pages.

Step 02 Held by the provider

The funds sit in the payment provider's balance — never on a Social Hub bank account. The regulated party stays the provider.

Refunded

The event missed its minimum, was cancelled, or a participant filed a report.

Paid out

Only after the event ended, a holding period passed, and nothing was disputed.

Three invariants hold the whole thing together: only a signed webhook can turn a booking into a paid ticket, the demo checkout disables itself the moment real keys exist, and every operation is idempotent, because webhooks arrive more than once and a payment system that double-counts is worse than one that does not run at all.

Built, then switched off. The entire payment layer — onboarding, payment intents, signed webhooks, refunds, payout batches, dispute reporting — ships in the codebase and stays dormant without a secret key. Until the company registration number comes through, the platform runs a clearly labelled demo checkout instead.

Mobile is not a narrower desktop

The brief I gave myself was "have a quick look at the mobile view". The audit was less quick than hoped: the navigation collided with itself on every page, one event card was around 450 pixels tall so exactly one event fitted on a screen, the explore filters scrolled sideways into invisibility, and a single page carried 33 tap targets under the 44-pixel minimum. It was a desktop site holding its breath.

The Social Hub mobile home screen with a compact hero, stacked search fields and category chips

Rebuilt mobile home: search pulled up, hero condensed

Mobile event detail page with a fact card for date, location and attendance, and a fixed RSVP bar at the bottom

Event detail: facts consolidated, RSVP bar pinned in reach

What I took away. Not the frameworks — those change every eighteen months anyway. What stuck is how differently you review a design when you are also the person who has to migrate the database at eleven at night: fewer states invented for their own sake, more decisions made once and shared, and a much shorter path between "that looks wrong" and "that is fixed".

Get in touch with me