SnoekByte LogoSnoekByte
Case Study · Live in Produktion
Lead-Plattform für lokale Fitnessstudios

Vom leeren Bildschirm zum ersten Kunden live — in acht Tagen.

Fit in de Buurt ist eine Lead-Plattform für lokale Fitnessstudios: Landingpages die konvertieren, ein Portal zur Nachverfolgung angerufener Leads, ein Postleitzahl-Verzeichnis und die Fakturierung drumherum. Design, Bau, Datenbank, Hosting und Betrieb — solo gebaut.

Live-Plattform ansehen
Rolle
Design, Bau, Datenbank, Hosting & Betrieb (solo)
Zeitraum
August 2026 · 8 Tage bis zum ersten Kunden live
Stack
Next.js 16 · React 19 · TypeScript · Tailwind 4 · Supabase · Resend · Vercel
Live
fitindebuurt.nl

Live auf fitindebuurt.nl · Row-Level-Security auf allem Privaten · Next.js 16, React 19, Supabase

8
Tage bis zum ersten Kunden live
±33k
Zeilen TypeScript (265 Dateien)
464
automatisierte Tests
Live
erster echter Kunde in Produktion

Das Problem

Ein kleines Fitnessstudio wirbt lokal, schickt Menschen auf sein Instagram oder eine allgemeine Website und verliert sie dort. Wer doch reagiert, kommt über eine DM, eine Mail oder eine Nachricht; die Inhaberin merkt sich im Kopf, wen sie zurückrufen muss. Zwei Tage später ist die Hälfte vergessen und das Interesse weg.

Die drei Dinge, die es dafür gibt, lösen jeweils nur einen Teil. Ein Website-Baukasten liefert eine Seite ohne Nachfassen. Ein CRM ist zu schwer für jemanden mit einer Handvoll Leads pro Monat. Ein Linktree bietet keinerlei Einblick. Und alles, was funktioniert, legt die personenbezogenen Daten ihrer Kunden an einen Ort, über den sie keine Kontrolle hat.

Was daraus wurde

Eine Plattform, die drei Arten von Besuchern zugleich bedient — den Sportler, das Studio und den Betreiber.

Für den Sportler

Die Startseite ist ein Verzeichnis: Postleitzahl eingeben und sehen, welche Studios, Fitnesscenter, Salons und Praxen am nächsten liegen — mit Entfernung, Bewertungen und einem Button zum Buchungssystem oder zur Lead-Seite. Ohne Cookies, ohne Konto, ohne dass wir speichern, wonach jemand sucht.

Für das Studio

Eine eigene Lead-Seite auf name.fitindebuurt.nl und fitindebuurt.nl/name, aus Blöcken gebaut und auf die Corporate Identity abgestimmt. Wer seine Nummer hinterlässt, landet sofort im Portal, mit einer Mail dazu. Im Portal steht eine Liste: wen rufe ich an. Pro Lead werden Anrufversuche erfasst, mit Notiz snoozen, als gewonnen oder verworfen markieren.

Für den Betreiber

Ein Editor, in dem ich eine Kundenseite aufbaue und veröffentliche, Statistik pro Version dieser Seite und Fakturierung mit Abonnements, Nummerierung, PDFs und einem nächtlichen Cronjob.

Es gibt nirgends einen Anruf-Button oder einen tel:-Link. Das ist die ganze Idee: Ein Besucher hinterlässt seine Daten und das Studio ruft zurück. So weiß die Inhaberin, wer interessiert war — auch wenn das Gespräch nicht sofort klappt.

Vier Entscheidungen, die das Projekt prägen

Entscheidungen, die sich durch die gesamte Codebasis ziehen — und den Unterschied zwischen fertig und hingeschludert machen.

1

Die Trennung zwischen Kunden steckt in der Datenbank, nicht in der Oberfläche

Jede Seite hat einen Eigentümer. Row-Level-Security in Postgres entscheidet, wer welche Zeile sieht; die App kann es nicht umgehen, ich auch nicht. Eine Testsuite versucht mit echten Zugangsdaten zweier Eigentümer, gegenseitig Leads zu lesen, zu ändern und zu löschen. Ohne diesen grünen Test geht nichts live.

2

Der Inhalt einer Seite steht an zwei Stellen, mit Absicht

Die Vorlage ist eine typisierte Datei, die mit satisfies LandingPagina endet — fehlt ein Text, schlägt der Build fehl. Was ich im Editor ändere, wird als Overlay in der Datenbank gespeichert und über die Vorlage gerendert. So behalte ich die Garantien des Compilers und kann Texte ändern, ohne zu deployen.

3

Veröffentlicht wird unter einem Namen, Zahlen gehören zu einer Version

Jede Veröffentlichung ist eine unveränderliche Zeile in pagina_versies. Die Tageszähler merken sich pro Version das Gezählte, also sehe ich, was "Kürzere Hero" gegenüber "Sommeraktion" brachte, und stelle eine alte Version mit einem Klick als Entwurf wieder her.

4

Alles auf Niederländisch, bis in die Datenbank

Spalten heißen belpogingen, snooze_tot, weggedrukt_op. Das liest sich für den Kunden und für mich gleich und hält den Abstand klein zwischen dem, was wir im Gespräch sagen, und dem, was im Code steht.

Drei Teile zum Hervorheben

Die Stellen, in die die meiste Denk- und Bauzeit floss.

Der Seiten-Editor

Links eine Live-Vorschau, rechts die Seite von oben nach unten: pro Block ein Panel mit allem, was dazugehört. Texte bearbeitest du in der Vorschau selbst — zeigen, klicken, tippen — und ein Besucher bekommt exakt dasselbe HTML. Die Akzentfarbe steht in einer CSS-Variablen; color-mix leitet fünf Töne ab, sodass jeder Block zu jeder CI passt.

Das Postleitzahl-Verzeichnis

Postleitzahlen gehen an den Locatieserver des Kadasters (PDOK): offen, gratis, ohne Schlüssel. Das Ergebnis speichern wir in einer eigenen Tabelle, ein zweiter Besucher mit derselben PLZ kostet keine Anfrage. Postgres berechnet die Entfernung und liefert nur Studios, die jede Bedingung erfüllen. Vom Besucher bewahren wir nichts: kein Cookie, keine IP.

Fakturierung

Abonnements pro Kunde, automatische Entwürfe aus einem nächtlichen Lauf, eine Rechnungsnummernreihe, die nicht springen darf, Beträge in Cent, MwSt. pro Zeile und ein PDF im Speicher. Eine gesendete Rechnung ist eingefroren: Datenbank-Trigger verweigern jede Änderung, weil eine gesendete Rechnung sieben Jahre gleich bleiben muss.

So etwas für Ihr Unternehmen nötig?

Wie es zusammengesetzt ist

Ein Next.js-Projekt bedient vier Arten von Besuchern, getrennt mit Route-Gruppen: das Verzeichnis, die Marketingseiten, die Kunden-Landingpages und die eingeloggte Seite. Subdomains laufen über proxy.ts, das die Supabase-Session auffrischt und alles hinter dem Login abschließt.

SchichtWahl
AppNext.js 16 (App Router), React 19, TypeScript strict
StylingTailwind CSS 4, eigene Komponenten, vollständig niederländische Oberfläche
Daten + AuthSupabase (Postgres, Auth, Storage), Region Frankfurt
ValidierungZod, auf beiden Seiten und auf den Umgebungsvariablen
MailResend, fünf transaktionale Mails mit einer Gestaltung
PDF@react-pdf/renderer, Rechnungen in Supabase Storage
HostingVercel, Wildcard *.fitindebuurt.nl, Cronjobs, Preview pro Push
SecretsDoppler; kein Schlüssel im Repo
MonitoringSentry, nur in Produktion
  • Zwei nächtliche Jobs auf Vercel hinter einem gemeinsamen Geheimnis: 06:00 Fakturierung, 04:00 Aufräumen abgelaufener Anfragen.
  • Keine Namen, Telefonnummern oder E-Mail-Adressen in Logs oder Fehlermeldungen, keine IP-Adressen in der Statistik.
  • Leads werden ausschließlich serverseitig geschrieben — der Browser hat kein Schreibrecht auf die Datenbank.
  • Ein gesnoozter Lead kommt von selbst zurück: Snooze ist kein Status, sondern ein Datum, kein Hintergrundjob, der stillstehen kann.

Qualität und Arbeitsweise

Ein Befehl ist das Tor: npm run check führt Typecheck, ESLint ohne Warnungen, Prettier, alle Unit-Tests und einen vollständigen Build aus. Was da nicht durchkommt, gilt nicht als fertig. Husky und lint-staged tun dasselbe bei jedem Commit, GitHub Actions wiederholt es bei jedem Push.

WasUmfang
Code265 Dateien, ± 33.000 Zeilen TypeScript
Datenbank27 Migrationen, 20 Tabellen, RLS auf allem Privaten
Unit-Tests412, in 37 Dateien
Browser-Tests (Playwright)52, in 9 Dateien
Vorlagen und Blöcke8 Vorlagen, 12 wiederverwendbare Blöcke
Commits94, in acht Tagen

Browser-Tests tun, was ein Mensch tut

Einloggen, einen Lead hereinholen, ihn snoozen, einen Block im Editor abschalten, veröffentlichen und prüfen, dass sich die öffentliche Seite mitändert. Genau dort sitzen die Fehler, die Typecheck und Unit-Tests nicht sehen.

Auffindbarkeit ist an vier Stellen festgelegt

robots.ts (mit dreiundzwanzig namentlich genannten AI-Crawlern), eine Sitemap, die Kundenseiten aus der Datenbank zieht, ein generiertes /llms.txt mit der ganzen Site in Markdown und strukturierte Daten pro Seitentyp — nie mehr als auf der Seite selbst steht.

Mit AI-Unterstützung gebaut, aber nicht auf gut Glück

Jeder Teil wurde zuerst als Plan im Repo ausgeschrieben — warum, welche Phasen, welche Abwägungen — und dann gebaut. Feste Vereinbarungen stehen in einer Regeldatei, die jede Session mitliest. Die Tests, die Typen und Row-Level-Security sind die Bremse.

Wo es jetzt steht

Die Site läuft, der erste echte Kunde ist live und im Verzeichnis, und die Fakturierung steht bereit für ihr erstes Abonnement.

Auf der Roadmap
  • Kartenansicht und eigene Übersichtsseiten pro Art und Ort
  • Verifizierte Google-Bewertungen
  • Export von Leads
  • Zwei-Faktor-Authentifizierung
  • A/B-Tests über zwei veröffentlichte Versionen zugleich

Von der Idee zur Live-Plattform

Maßgeschneiderte Software, die bleibt.

Eine Lead-Plattform, ein Portal, ein Webshop oder ein internes Tool — gebaut mit Tests, Typen und Datenschutz als Fundament. Lassen Sie uns besprechen, was Sie brauchen.

Kontakt