Es war 23:43 Uhr an einem Donnerstag und ich starrte auf 340 Zeilen React-Code, den GPT-4 mit absoluter Zuversicht generiert hatte. Sauber. Gut kommentiert. Völlig kaputt in Produktion. Der Custom Hook verwaltete den State so, dass er zu stillen Re-Render-Schleifen führte -- der Art, die keine Fehler werfen, sondern einfach leise deine Performance zerstören, bis ein Kunde dich Freitag morgens anruft und fragt, warum ihre Checkout-Seite neun Sekunden zum Laden braucht.
Diese Nacht hat mir mehr über Prompt Engineering beigebracht als jedes YouTube-Tutorial oder Twitter-Thread je könnte. Und ich hatte seitdem viele solcher Nächte.
Ich baue seit neun Jahren im Web. Bei Seahawk Media haben wir über 12.000 Websites deployed -- WordPress, Headless Builds, massgeschneiderte React Apps, WooCommerce Stores mit ernsthaftem Transaktionsvolumen. KI-Coding-Assistenten sind richtig in meinen Workflow um Anfang 2023 eingezogen, und ich bin zwischen dem Gedanken, dass sie wunderbar sind, und dem Impuls, meinen Laptop in die Themse zu werfen, hin und her geschwankt.Seahawk Media we've shipped well over 12,000 sites -- WordPress, headless builds, bespoke React apps, WooCommerce stores handling serious transaction volume. AI coding assistants entered my workflow properly around early 2023, and I've swung between thinking they're miraculous and wanting to throw my laptop into the Thames.
Hier ist, was ich wirklich gelernt habe. Auf die harte Tour.
---
Das Modell kennt deine Codebase nicht. Du musst es ihr sagen.
Das klingt offensichtlich. In der Praxis ist es das nicht.
Der grösste Fehler, den ich Entwickler machen sehe -- inklusive mir selbst die ersten sechs Monate -- ist, ein LLM wie einen Senior Engineer zu behandeln, der bereits all deinen Code gelesen hat. Du fragst "schreib eine Funktion zur Benutzerauthentifizierung" und es schreibt etwas technisch Korrektes im Vakuum. Aber dein Projekt nutzt Supabase, nicht Firebase. Deine Tokens sitzen in httpOnly Cookies, nicht localStorage. Dein Error-Format ist { status, message, data }, nicht das, auf das das Modell standardmässig gefallen ist.Supabase, not Firebase. Your tokens live in httpOnly cookies, not localStorage. Your error format is { status, message, data }, not whatever the model defaulted to.
Das Modell liegt nicht falsch. Es kennt dich nur nicht.
Gib Ihm jedes Mal einen Project Preamble
Ich starte jede bedeutsame Coding-Session jetzt mit dem, was ich einen „Context Block" nenne. Dauert etwa 90 Sekunden zu schreiben. Sieht ungefähr so aus:
- Stack: Next.js 14 (App Router), TypeScript, Supabase, Tailwind CSS 3.4Next.js 14 (App Router), TypeScript, Supabase, Tailwind CSS 3.4
- State: Zustand, nirgendwo Redux
- Auth: Supabase Auth mit httpOnly Cookies über Middleware
- Error shape: { success: boolean, error?: string, data?: unknown }
{ success: boolean, error?: string, data?: unknown } - Stilkonvention: Utility-first, keine Custom-CSS-Dateien außer wenn absolut notwendig
Füge das vor jeder nicht-trivialen Anfrage ein. Ich mache das in Cursor, indem ich eine _context.md Datei im Project Root behalte. Zwei Tastenanschläge zum Einfügen. Die Output-Qualität springt merklich hoch -- weniger Annahmen, weniger Dinge, die ich heraureissen muss.Cursor by keeping a _context.md file in the project root. Two keystrokes to paste. The output quality jumps noticeably -- fewer assumptions, fewer things I have to rip out.
---
Präzision ist das ganze Spiel
Zurück in 2022, bevor ich AI intensiv nutzte, gab mir ein Client ein Briefing, das buchstäblich zwei Sätze waren: „Baue uns ein Buchungssystem. Mach es gut." Wir verbrachten drei Wochen damit, hin und her über den Umfang zu diskutieren. Diese Erfahrung ist mir geblieben und prägt direkt, wie ich jetzt Prompts schreibe.
Vage Anfrage → vager Code. Jedes Mal.
„Schreib eine Funktion, die Orders abruft" wird dir etwas geben. „Schreib eine TypeScript async Funktion namens fetchOrdersByUser, die userId: string akzeptiert, die orders Tabelle in Supabase abfragt, wo user_id passt und status nicht cancelled ist, sortiert Ergebnisse nach created_at absteigend und gibt Order[] zurück oder wirft einen typisierten Error" wird dir etwas geben, das du tatsächlich ausliefern kannst.fetchOrdersByUser that accepts a userId: string, queries the orders table in Supabase where user_id matches and status is not cancelled, orders results by created_at descending, and returns Order[] or throws a typed error" will get you something you can actually ship.
Der Unterschied liegt nicht in der Fähigkeit des Modells. Es ist die Präzision der Anfrage.
Was in eine Code-Anfrage gehört
- Funktionsname und Signatur -- lass das Modell keine Naming Conventions erfinden -- don't let the model invent naming conventions
- Input-Typen und Output-Typen -- TypeScript Generics falls relevant -- TypeScript generics if relevant
- Die Datenquelle -- welche Tabelle, welcher API Endpoint, welche Cache Layer -- which table, which API endpoint, which cache layer
- Edge Cases, die du bereits kennst -- "behandle den Fall, wo das Array leer ist" -- "handle the case where the array is empty"
- Was NICHT zu tun -- "nutze useEffect dafür nicht, nutze stattdessen eine Server Action" -- "don't use useEffect for this, use a server action"
Das letzte Punkt ist wichtiger, als die Leute denken. Dem Modell zu sagen, was es vermeiden sollte, spart enorm viel Zeit. Ich habe angefangen, pro Projekt eine kleine Notiz zu "Anti-Patterns" zu führen -- Dinge wie "keine Client-Komponenten, es sei denn, Benutzerinteraktion erfordert es" -- und ich füge relevante Zeilen in Prompts für dieses Projekt ein.
---
Verkette deine Prompts. Frag nicht nach allem auf einmal.
Seahawk hatte Ende 2023 einen Fintech-Client -- ich sage nicht, wer -- wo wir einen mehrstufigen KYC-Flow entwickelt haben. Komplexes Zeug. Dokument-Upload, Liveness-Check-Integration, Status-Polling. Ich habe den Fehler gemacht und GPT-4 früh gebeten, "die vollständige KYC-Flow-Komponente zu bauen." Es spuckte 600 Zeilen heroisch aussehenden Müll aus. Verflochtene Logik, vermischte Concerns, keine echte Trennung zwischen UI-State und Business-Logik.
Also habe ich es verworfen und mit einer Chain neu angefangen.
Erster Prompt: „Design the state machine for a 4-step KYC flow. Steps: identity, document upload, liveness, review. Give me the state type and transitions only, no UI.""Design the state machine for a 4-step KYC flow. Steps: identity, document upload, liveness, review. Give me the state type and transitions only, no UI."
Zweite Aufforderung: „Gegeben diese State Machine [einfügen], schreibe den Zustand Store.""Given this state machine [paste], write the Zustand store."
Dritte Aufforderung: „Gegeben dieser Store [einfügen], schreibe die StepIdentity Komponente. Nur dieser Schritt.""Given this store [paste], write the StepIdentity component. Just this step."
Die Ausgabe des verketteten Ansatzes war verwendbar. Nicht perfekt -- ich schrieb immer noch etwa 30% neu -- aber verwendbar. Der monolithische Ansatz brachte mir nichts.
Anthropics eigene Anleitung zum Prompting spricht davon, komplexe Aufgaben in Teilaufgaben zu unterteilen, und ehrlich gesagt, das entspricht genau dem, was ich durch Versuch und Irrtum herausgefunden habe. Zerlege das Problem, bevor du deine Codebase zerlegi. talks about breaking complex tasks into subtasks, and honestly, this aligns exactly with what I found through trial and error. Break the problem down before you break your codebase.
---
Lass Es Mit Sich Selbst Argumentieren
Das ist eine, über die ich völlig zufällig gestolpert bin. Ich habe eine generierte Utility-Funktion überprüft und statt sie einfach auszuführen, habe ich eine Folgefrage hinzugefügt: „Welche potenziellen Bugs oder Grenzfälle hat der Code, den du gerade geschrieben hast?""What are the potential bugs or edge cases in the code you just wrote?"
Das Modell fand drei Probleme, die es nicht berücksichtigt hatte. Eines davon war ein echtes Problem -- eine Race Condition in einer Async-Schleife, die in der Produktion ein Albtraum zum Debuggen gewesen wäre.
Das mache ich jetzt routinemäßig. Schreib den Code, frag es dann, den Code zu kritisieren. Dann frag es, die Kritik zu beheben. Es fühlt sich leicht absurd an -- das Modell zu bitten, seine eigene Arbeit zu überprüfen -- aber es findet konsistent Dinge, die ich erst nach einer schmerzhaften Debugging-Session gefunden hätte.
Du kannst das noch weiter treiben. Nachdem du eine funktionierende Funktion hast, versuche: „Schreibe das mit Fokus auf Performance um" oder „Wie würde sich das unter hoher Concurrency verhalten?" Die Antworten sind nicht immer anwendbar, aber etwa 40 % der Zeit decken sie etwas auf, das es wert ist, danach zu handeln."Rewrite this with a focus on performance" or "How would this behave under high concurrency?" The answers aren't always applicable, but about 40% of the time they surface something worth acting on.
---
Der „Role + Constraint"-Rahmen
Es gibt ein Prompt-Muster, das ich ständig nutze und das ich mir schon im ersten Jahr hätte überlegen sollen. Es funktioniert so: „Du bist ein [spezifischer Typ von Engineer]. Deine Einschränkung ist [harte Regel]. Jetzt [Aufgabe].""You are a [specific type of engineer]. Your constraint is [hard rule]. Now [task]."
Beispiel: "Du bist ein Backend-Engineer, dem Datenbankabfrage-Effizienz am Herzen liegt. Deine Einschränkung ist, dass du nicht mehr abrufen kannst, als für diesen Render nötig ist -- kein Over-Fetching. Schreib eine Supabase-Abfrage für das Admin-Dashboard, die die Bestellanzahl, Gesamtumsatz und die fünf neuesten Bestellungen zurückgibt.""You are a backend engineer who cares deeply about database query efficiency. Your constraint is that you cannot fetch more than what's needed for this render -- no over-fetching. Write a Supabase query for the admin dashboard that returns order count, total revenue, and the five most recent orders."
Dieses Framing tut zwei Dinge. Es richtet die "Persona" des Modells auf das aus, was ich wirklich brauche. Und die Einschränkung fungiert als Leitplanke -- etwas, das das Modell explizit selbst überprüft, während es generiert.
OpenAIs Prompting-Best-Practices beschreiben eine ähnliche Idee zum Geben einer Persona mit expliziten Anweisungen. Lesenswert, wenn du das noch nicht getan hast, aber ich würde sagen, der Constraint-Teil wird in ihrer Dokumentation unterbewertet. describe a similar idea around giving the model a persona with explicit instructions. Worth reading if you haven't, though I'd say the constraint piece is underemphasised in their docs.
Vergleiche die Ausgabe dieses gerahmten Prompts mit „schreib eine Supabase-Query für das Admin-Dashboard." Tag und Nacht. Wirklich.
---
Wann du mit Prompting aufhören und einfach den Code schreiben solltest
Das ist der Teil, den niemand laut aussprechen will.
KI-Codierungstools sind brillant bei: Boilerplate-Code, CRUD-Operationen, Utility-Funktionen, dem Schreiben von Tests für bereits vorhandenen Code, der Übersetzung zwischen Formaten (JSON-Schema zu TypeScript-Typ, SQL zu Supabase-Abfrage, etc.) und ersten Entwürfen von Dingen, die du später umfassend modifizieren wirst.
Sie sind wirklich schlecht darin: die tatsächliche Architektur deiner App zu verstehen, zu wissen, welcher Trade-off bei deiner spezifischen Skalierung wichtig ist, etwas zu schreiben, das eine knifflige zustandsbehaftete Interaktion berührt, ohne intensive Anleitung, und alles, wo die Spezifikation grundlegend mehrdeutig ist.
Ich habe mir jetzt eine persönliche Regel gesetzt: Wenn ich mehr als vier Folgeprompts gesendet habe, um ein Code-Stück richtig hinzubekommen, schließe ich den Chat und schreibe es selbst. Die Zeitkosten des Prompt-Debuggings können die Zeitkosten des reinen Schreibens übersteigen, besonders bei allem unter etwa 50 Zeilen.
Die Stack Overflow Developer Survey 2024 fand, dass 76% der Entwickler KI-Tools nutzen oder planen zu nutzen -- aber die gleichen Daten zeigten relativ niedriges Vertrauen in die Genauigkeit. Diese Lücke zwischen Nutzung und Vertrauen ist genau der Ort, an dem gutes Prompt Engineering lebt.Stack Overflow Developer Survey 2024 found that 76% of developers are using or planning to use AI tools -- but the same data showed relatively low trust in accuracy. That gap between usage and trust is exactly where good prompt engineering lives.
---
Versioniere deine Prompts wie du deinen Code versionierst
Letztes Jahr habe ich angefangen, einen prompts/-Ordner in Projekten zu führen, bei denen KI-Unterstützung erheblich ist. Markdown-Dateien. Eine pro Hauptfeaturebereich. Wenn ein Prompt besonders gute Ausgabe produziert, speichere ich ihn. Wenn ich eine bessere Version finde, aktualisiere ich die Datei.prompts/ folder in projects where AI assistance is significant. Markdown files. One per major feature area. When a prompt produces particularly good output, I save it. When I find a better version, I update the file.
Klingt obsessiv. Es hat mir beim letzten großen Projekt wahrscheinlich sechs Stunden gespart -- ein Headless-WooCommerce-Build für einen Einzelhandel, der von Shopify wechselte. Ich nutzte einen Product-Query-Prompt (mit kleineren Änderungen) über vier verschiedene Komponenten hinweg, anstatt den Kontext von Grund auf neu zu engineeren.
Versionskontrolle es. Ernsthaft. Prompt-Qualität ist reproduzierbar, wenn du Prompts als Artefakte behandelst statt als Wegwerfeinput. LangChain formalisiert diese Idee in einem Framework-Kontext, aber du brauchst kein Framework -- ein Ordner mit Markdown-Dateien reicht für die meisten Agency-Workflows.LangChain's prompt templates formalise this idea in a framework context, but you don't need any framework -- a folder of Markdown files is enough for most agency workflows.
---
FAQ
Ist Prompt Engineering wirklich eine übertragbare Fähigkeit oder nur modellspezifisch?
Größtenteils übertragbar. Die Kernprinzipien -- Spezifität, Kontext-Setzung, Chaining, Kritik-Schleifen -- gelten für GPT-4, Claude 3.5 Sonnet, Gemini und alles, was danach kommt. Die Syntax unterscheidet sich etwas und manche Modelle reagieren besser auf bestimmte Rahmungen, aber die zugrundeliegende Logik bleibt bestehen. Ich habe festgestellt, dass Claude gut auf explizite Einschränkungen reagiert; GPT-4 reagiert gut auf Beispiele. Kleine Unterschiede, gleiche Grundlagen.syntax varies a bit and some models respond better to certain framing, but the underlying logic holds. I've found Claude tends to respond well to explicit constraints; GPT-4 responds well to examples. Minor differences, same fundamentals.
Wie gehst du mit von KI generiertem Code in Code Reviews um?
Wie jeder andere Code auch. Wenn es in die Produktion geht, wird es überprüft. Punkt. Ich habe aufgehört, in PRs bei Seahawk zu markieren, „das wurde von KI generiert" -- es wurde zu einer Ablenkung -- Reviewer würden es anders untersuchen, manchmal zu streng, manchmal nicht streng genug. Der Code besteht oder fällt auf seine eigenen Meriten. Was ich kennzeichne: alle Abschnitte, wo die Logik nicht offensichtlich ist und ich keine Inline-Kommentare hinzugefügt habe, die das Vorgehen erklären.
Verwendest du System Prompts oder nur Chat Prompts?
Beides. In Cursor nutze ich die .cursorrules-Datei für persistente projektweite Anweisungen -- Dinge, die ich sonst jedes Mal einfügen würde. Für einmalige Aufgaben in der ChatGPT- oder Claude-Web-UI ist alles im Chat. Der .cursorrules-Ansatz hat die Wiederholung erheblich reduziert und das Modell bleibt über eine lange Session hinweg konsistenter..cursorrules file for persistent project-level instructions -- things I'd otherwise paste every time. For one-off tasks in the ChatGPT or Claude web UI, it's all in the chat. The .cursorrules approach has meaningfully reduced repetition and the model stays more consistent across a long session.
Wie ist deine ehrliche Einschätzung: Ersetzen KI-Systeme Developer?
Es ersetzt bestimmte Aufgaben, nicht Entwickler. Die Urteilsfindung -- was man bauen soll, wie man es architektiert, welcher Trade-off zu dieser konkreten Client-Situation passt -- das ist weit entfernt von Automatisierung. Wenn überhaupt, werden die Entwickler unter Druck gesetzt, die rein ausführungsorientiert waren, nicht design- oder architekturorientiert. Schärfe deine Urteilsebene. Das ist der verteidigbare Teil.tasks, not developers. The judgment calls -- what to build, how to architect it, which trade-off fits this client's actual situation -- those are nowhere near automated. If anything, the developers getting squeezed are the ones who were purely execution-oriented, not design or architecture-oriented. Sharpen the judgment layer. That's the defensible bit.
---
Neun Jahre im Web-Entwicklung, und die grundlegende Lektion wiederholt sich immer wieder: Die Qualität deines Outputs wird durch die Qualität deiner Inputs bestimmt. Das galt, als es noch um Kundenbriefs ging. Es gilt jetzt mit Prompts.the quality of your output is determined by the quality of your inputs. That was true when it was client briefs. It's true now with prompts.
Das Modell ist ein schneller, gelegentlich brillanter, häufig überselbstbewusster Junior-Developer. Behandle es entsprechend.
