Am 27. Juli haben wir deine eigene Infrastruktur aufgebaut, VPS, Coolify, GitHub, und ein Hello World ins Netz gestellt. Heute kommt der Baustein dazu, der aus einer Seite eine Anwendung macht: eine Datenbank. Und Linear als System für alles, was danach noch kommt.
Zu groß gedacht, und am Abend läuft nichts. Nimm etwas Kleines, das dich wirklich betrifft. Ausbauen kannst du ab morgen.
Was heute liegen bleibt, nimmst du als Liste mit.
Dies hier ist kein Wettbewerb. Die Basis ist das vollständige Lernziel dieser Session. Wer die Basis schafft, hat alles erreicht, worum es geht, und erhält heute Abend eine funktionierende Anwendung.
Plus und Kür sind für alle, die schneller fertig sind. Sie sind aufklappbar, damit sie niemanden ablenken. Es ist ausdrücklich in Ordnung, sie heute nicht zu öffnen.
Die Frage kommt stets, deshalb vorweg. Es sind drei getrennte Orte:
localhost:5173, und nur du siehst sie.Rechner und Datenbank werden über zwei Werte in einer Datei namens .env verbunden. Heute arbeiten wir auf deinem Rechner, der Weg auf den VPS steht am Ende als Ausblick.
Vorab · einmalig
Claude Code muss laufen, und du solltest dich einmal eingeloggt haben. Prüfe dabei dein Kontingent. Wir arbeiten mit Opus 5 (falls möglich, stets auf Max), und das verbraucht spürbar.
Auf supabase.com registrieren. Kostenlos, Anmeldung über GitHub geht am schnellsten. Noch kein Projekt anlegen, das machen wir gemeinsam.
Auf linear.app registrieren, falls noch nicht geschehen. Wir nutzen es in der Session als Dokumentation und Arbeitsliste (Backlog).
Suche die Claude-Code-Sitzung heraus, in der wir VPS, Coolify und GitHub eingerichtet haben. Öffne sie einmal und lass sie geöffnet. Wir benötigen daraus gleich ein Dokument.
ca. 17 Minuten
Nicht jede Anwendung braucht eine Datenbank. Sie braucht eine, sobald Daten länger leben sollen als ein Seitenaufruf, oder sobald mehr als eine Person darauf zugreift. Beides trifft auf das zu, was du heute baust.
Es gibt kein vorgegebenes Thema. Du wählst jetzt, woran du die nächsten zwei Stunden arbeitest.
Diese Liste ist Inspiration, keine Auswahl. Wer etwas Eigenes hat, nimmt das.
Der Engpass beim Bauen mit KI ist nicht das Werkzeug. Es ist, wie genau du sagen kannst, was du willst. Wer den Intent aufschreibt, statt ihn zu tippen, kann ihn überarbeiten. Und die Datei trägt beim nächsten Projekt genauso.
Öffne dafür einen leeren Texteditor. Noch kein anderes Werkzeug. Speichere die Datei als intent.md. Später liegt sie neben architektur.md im Projektordner. In Schritt 03 kommt ihr Inhalt in den Startprompt.
Ich moechte [WAS] verwalten. Die wichtigsten Angaben: [FELD 1], [FELD 2], [FELD 3], ... Anlegen und als Tabelle anzeigen reicht als Umfang. Das Ziel: [was es dir nutzt]
Unentschlossen? Nimm dieses Beispiel eins zu eins. Es wird die ganze Seite hindurch weitergeführt, mit fertigem SQL in Schritt 04.
Ich moechte meine beruflichen Kontakte verwalten. Die wichtigsten Angaben: Vorname, Nachname, Firma, E-Mail, Telefon, Notiz. Anlegen und als Tabelle anzeigen reicht als Umfang. Das Ziel: Ich sehe auf einen Blick, wen ich kenne und worueber wir gesprochen haben.
ca. 5 Minuten
Der Intent steht. Jetzt das erste Werkzeug.
Leg ein Projekt an, benannt nach dem WAS aus deiner intent.md. Ein Wort oder zwei, kein Satz. Kein neues Team: Linear hat bei der Registrierung schon Workspace und Team angelegt. Der Name, den du dort vergeben hast, bestimmt Team und Kürzel. Wer das Kürzel ändern will, findet es in den Team-Einstellungen unter General, muss es aber nicht. Issue-Nummern vergibt Linear selbst, von KÜRZEL-1 aufsteigend. Du tippst nie eine Nummer. Im kostenlosen Plan sind zwei Teams möglich, Projekte unbegrenzt. Der Anwendungsfall wird als Projekt in diesem Team angelegt.
Genau zwei Issues:
Ein erledigter Eintrag und ein offener. Mehr braucht ein Backlog nicht, um verständlich zu sein.
ca. 8 Minuten
Weshalb eine neue Sitzung und nicht die alte: Die Sitzung des 27. Juli ist voll mit Server-Einrichtung. Für ein neues Vorhaben braucht es einen frischen Ordner und einen frischen Kontext, sonst arbeitet Claude Code gegen alten Ballast an.
Verloren geht dabei nichts. Bevor wir die alte Sitzung schließen, holen wir das Wissen heraus, das wir heute benötigen.
Öffne die Sitzung des 27. Juli und gib dort diesen Auftrag:
Fasse die Infrastruktur zusammen, die wir hier aufgebaut haben. Schreibe eine Datei architektur.md, die beschreibt: welcher VPS bei welchem Anbieter, wie Coolify konfiguriert ist, wie das GitHub-Repository angebunden ist und wie ein Deployment ablaeuft. Schreibe sie so, dass eine andere KI-Sitzung damit sofort arbeiten kann, ohne diesen Chat zu kennen.
Leg einen neuen Ordner an, benannt nach dem WAS aus deiner intent.md. Kopiere architektur.md und intent.md hinein.
Claude Code Desktop öffnen, neue Sitzung, diesen Ordner wählen, Modell Opus 5, Plan Max. Mehr passiert hier noch nicht, der erste Auftrag kommt in Schritt 03.
architektur.md in deinem neuen Ordner. Oder arbeite zunächst ganz ohne Architekturdokument weiter. Für die heutige Session ist es nicht zwingend, es macht später beim Deployment den Unterschied.
# Architektur ## Server Anbieter: [z. B. Hostinger] Produkt und Groesse: [z. B. KVM 2, 2 vCPU, 8 GB RAM, 100 GB SSD] Betriebssystem: [z. B. Ubuntu 24.04 LTS] Adresse oder IP: [z. B. 203.0.113.10] ## Coolify Oberflaeche erreichbar unter: [z. B. http://203.0.113.10:8000] Bereits angelegte Anwendung: [z. B. hello-world] Zugewiesene Domain: [z. B. hello.meine-domain.de] ## GitHub Repository: [z. B. meinname/hello-world] Anbindung an Coolify: [z. B. ueber die Coolify-GitHub-App] ## Deployment So kommt eine Aenderung ins Netz: [z. B. Push auf main, Coolify baut automatisch neu, nach etwa einer Minute ist die Domain aktuell]
ca. 12 Minuten
Der erste Auftrag in einer neuen Sitzung entscheidet über den ganzen Abend. Deshalb schauen wir uns an, woraus er besteht, bevor du ihn abschickst. Er hat vier Teile:
architektur.md und intent.md. Claude Code liest beide zuerst.intent.md, wörtlich in den Prompt eingesetzt.Lies zuerst architektur.md und intent.md in diesem Ordner. Jetzt moechte ich einen naechsten Schritt gehen und zwei Bausteine ergaenzen: Supabase als Datenbank und Linear als System fuer meinen Backlog. Die Anwendung selbst baust du als Vite-Projekt mit React in diesem Ordner. Mein Anwendungsfall steht in intent.md. Hier der Inhalt: [HIER DEN INHALT AUS intent.md EINSETZEN] Die Anwendung muss Eintraege anlegen und als Tabelle anzeigen, mit einer Spalte je Feld. Fuehre mich bitte 1:1 und sehr konkret durch den Prozess. Ich habe noch nie selbst Code geschrieben. Erklaere mir bei jedem Schritt kurz, was passiert und weshalb, bevor du ihn ausfuehrst. Fang mit meiner Feldliste an: pruefe sie, ergaenze, was fehlt, und streiche, was zu viel ist. Begruende beides kurz und warte auf meine Bestaetigung, bevor du die Tabelle anlegst.
Die beiden letzten Absätze sind der eigentliche Kern. Ohne sie baut Claude Code fünfzehn Minuten am Stück durch, am Ende läuft etwas, und du verstehst nichts davon. Mit ihnen hältst du das Tempo in der Hand und siehst jeden Schritt einzeln.
Das ist das Lernziel dieses Abends, nicht das SQL.
Während Claude Code deine Feldliste prüft, legst du im Browser das Projekt an. In Supabase auf New project, Namen vergeben, Datenbank-Passwort setzen, als Region Frankfurt wählen. Das Passwort benötigst du heute nicht, notiere es trotzdem. Die Einrichtung dauert etwa eine Minute.
Danach auf Project Settings, dort API. Zwei Werte stehen dort:
https://abcdefgh.supabase.coeyJBeide Werte fügst du direkt in den Claude-Chat ein, mit einem Satz wie: „Das sind meine Supabase-Zugangsdaten, du brauchst sie gleich." Kein Zwischenspeichern in Notizen oder Dateien. Der anon key ist für die Öffentlichkeit bestimmt und darf dort stehen.
ca. 5 Minuten
Nach dem Abschicken des Startprompts arbeitet Claude. Diese Zeit nutzen wir.
Eine Tabelle mit aktivierter Zugriffssperre gibt nichts heraus, bis eine Regel es erlaubt. Wer das nicht weiß, sucht den Fehler in seiner Anwendung, obwohl er in der Datenbank sitzt.
Gleich taucht in der .env das Präfix VITE_ auf. Beides funktioniert gleich: Standardmäßig ist nichts freigegeben. Freigabe passiert ausdrücklich.
ca. 30 Minuten
Dieser Schritt hat eine feste Reihenfolge. Claude Code führt, diese Seite hält die Spur.
Claude legt das Vite-Projekt an, lädt die Abhängigkeiten und startet npm run dev. Im Terminal steht danach eine Adresse, meist http://localhost:5173. Öffne sie im Browser. Das ist deine Anwendung, noch ohne Daten.
npm run dev läuft, läuft deine Seite. Schließt du das Fenster, ist sie weg. Für weitere Befehle öffnest du ein zweites Terminal.Du öffnest keinen Texteditor. Der Dateiname beginnt mit einem Punkt und wird von Finder und Explorer ausgeblendet. TextEdit speichert als RTF, der Windows-Editor hängt .txt an. Aus .env wird .env.txt, und nichts funktioniert.
Stattdessen dieser Auftrag an Claude:
Lege eine .env im Projektordner an mit VITE_SUPABASE_URL und VITE_SUPABASE_ANON_KEY, trage die Werte von oben ein, ergaenze .env in der .gitignore und zeige mir danach den Inhalt der Datei.
Den Inhalt sollst du sehen, nicht schreiben müssen.
Vite reicht nur Variablen an den Browser weiter, deren Name mit VITE_ beginnt. Das ist kein Namensschema, sondern eine Freigabe. Diese beiden Werte landen im Browser und sind für jeden lesbar. Deshalb steht dort der anon key und niemals der service_role key. Dasselbe Prinzip wie die Zugriffssperre aus Schritt 03: Standardmäßig ist nichts freigegeben.
npm run dev.Claude hat keinen Zugriff auf deine Datenbank. Er schreibt das SQL, ausführen musst du es selbst im SQL Editor von Supabase.
Für die Blaupause aus Schritt 01, Kontakte, sind beide Blöcke fertig ausformuliert. Bei einem eigenen Anwendungsfall tauschst du nur den Tabellennamen. Die Spalten stehen ausschließlich im ersten Block.
create table kontakte ( id uuid primary key default gen_random_uuid(), angelegt_am timestamptz not null default now(), vorname text not null, nachname text not null, firma text, email text, telefon text, notiz text ); alter table kontakte enable row level security;
Das alter table gehört dazu: Tabellen aus dem Table Editor sind automatisch gesperrt, Tabellen aus dem SQL Editor nicht. Wer das vergisst, hat eine offene Tabelle im Netz.
Zwei Beispielzeilen, damit Wegmarke 1 etwas zu zeigen hat:
insert into kontakte (vorname, nachname, firma, email, telefon, notiz) values ('Erika', 'Mustermann', 'Mustermann GmbH', '[email protected]', '+49 170 1234567', 'Kennengelernt auf der Messe'), ('Max', 'Beispiel', 'Beispiel AG', '[email protected]', '+49 170 7654321', 'Rueckruf vereinbart');
create policy "lesen" on kontakte for select using (true); create policy "anlegen" on kontakte for insert with check (true); create policy "aendern" on kontakte for update using (true); create policy "loeschen" on kontakte for delete using (true);
using (true): Das heißt „jeder darf alles". Für heute ist das richtig, für echte Daten ist es falsch. Sobald deine Anwendung im Netz steht und echte Daten enthält, gehört dort eine Regel hin, die an den angemeldeten Nutzer gebunden ist.
Eine leere weiße Fläche ist die schlechteste Antwort, die eine Anwendung geben kann. Wer davor sitzt, weiß nicht, ob sie lädt, leer ist oder kaputt.
Behandle drei Faelle sauber: Waehrend die Daten geladen werden, zeige einen Ladehinweis. Wenn noch keine Eintraege vorhanden sind, zeige stattdessen einen kurzen Hinweis mit der Aufforderung, den ersten Eintrag anzulegen. Und falls die Datenbank einen Fehler zurueckgibt, zeige eine verstaendliche Meldung statt einer leeren Seite.
Der dritte Fall zahlt sich aus. Wenn heute Abend etwas klemmt, siehst du damit sofort, woran es liegt.
Mache die Eintraege bearbeitbar: Ein Klick auf einen Eintrag oeffnet die Felder zum Aendern, Speichern schreibt die Aenderung in die Datenbank zurueck. Ergaenze ausserdem bei jedem Eintrag einen Loeschen-Knopf, der den Eintrag nach einer Rueckfrage aus der Datenbank entfernt.
Erst wenn alle drei Wegmarken von Hand erledigt sind. Wer die Tabelle nie selbst im Table Editor gesehen hat, versteht in Schritt 05 nicht, was die zwei Fenster zeigen.
Danach den Supabase MCP in Claude Code verbinden. Claude legt dann Tabellen und Policies selbst an, ohne Wechsel in den Browser. Als Beispiel: eine zweite Tabelle.
service_role key: kein Token ins Repository, kein Token in einen Chat.
ca. 8 Minuten
Nichts tun. Terminal offen lassen, Rechner nicht zuklappen.
Zurück im Call: Schreib in einem Wort in den Chat, was gerade auf deinem Bildschirm steht.
ca. 12 Minuten · alle gemeinsam
Stell zwei Browserfenster nebeneinander. Links deine Anwendung aus Schritt 04 auf localhost, mit Formular und Tabelle. Rechts in Supabase der Table Editor mit deiner Tabelle: Das Raster zeigt die Datensätze, und Insert row öffnet die Eingabefelder.
Leg links über dein Formular einen Eintrag an, lade rechts neu. Die Zeile ist da. Dann umgekehrt: leg rechts über Insert row eine Zeile an, lade links neu. Sie erscheint.
Falls deine Anwendung noch nicht schreiben kann, prüf nur die Leserichtung: rechts eine Zeile anlegen, links neu laden. Der Punkt ist derselbe.
Der Punkt daran, ausgesprochen: Deine Anwendung und deine Daten sind zwei getrennte Dinge. Die Anwendung läuft auf deinem Rechner. Die Daten liegen in Frankfurt. Du könntest die Anwendung morgen löschen und neu bauen, die Daten wären noch da.
Zwei bis drei Teilnehmer zeigen ihre Anwendung. Der Rest schaut zu.
ca. 10 Minuten
Heute steht überall using (true): jeder darf alles. Für echte Daten muss die Regel an den angemeldeten Nutzer gebunden sein.
Die Regel steht in der Datenbank, nicht im Programm. Deshalb kann sie niemand umgehen, indem er die Anwendung verändert.
Die Issues von heute und das Backlog sind dieselbe Sorte Eintrag. Das eine ist erledigt, das andere noch nicht. Trag Ergebnisse ein, beginnend mit dem Punkt von eben:
Deine Anwendung läuft bisher nur lokal. Der Weg auf den eigenen VPS ist dir bekannt, das Hello World steht ja schon dort. Bei einer Anwendung mit Datenbank sind zwei Dinge anders:
.env gehört nicht ins Repository. Die beiden Werte hinterlegst du in Coolify als Umgebungsvariablen.Linear MCP in Claude Code verbinden. Danach schreibt Claude die offenen Punkte aus der Liste oben selbst als Issues, statt dass du sie abtippst.
service_role key und beim Supabase-Token: kein Token ins Repository, kein Token in einen Chat.
Und der nächste Schritt danach, nicht der heutige: Claude arbeitet nicht mehr nur an deinem Code. Mit MCP greift er auch auf deine Datenbank und dein Backlog zu.
Diese Seite bleibt online. Wenn du in der Session nicht mitgekommen bist oder gar nicht dabei warst, arbeite sie in Ruhe durch. Die Schritte funktionieren einzeln, nur der gemeinsame Teil in Schritt 05 braucht die Gruppe.