Es war 23:43 Uhr an einem Donnerstag und ich starrte auf 340 Zeilen React-Code, den GPT-4 mit absoluter Sicherheit generiert hatte. Sauber. Gut kommentiert. Völlig kaputt in der Produktion. Der Custom Hook verwaltete den State auf eine Weise, die stille Re-Render-Schleifen verursachte — die Art, die keine Fehler wirft, sondern einfach stillschweigend deine Performance ruiniert, bis ein Kunde dich Freitagmorgens anruft und fragt, warum die 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 deployt — WordPress, Headless Builds, Custom React Apps, WooCommerce Stores mit ernsthaftem Transaktionsvolumen. KI-Coding-Assistenten sind Anfang 2023 ordentlich in meinen Workflow gekommen, und ich bin zwischen der Überzeugung, dass sie Wunder vollbringen, und dem Wunsch hin und her geschwankt, meinen Laptop in die Themse zu werfen.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ößte Fehler, den ich Entwickler machen sehe — auch ich selbst die ersten sechs Monate — ist, ein LLM wie einen Senior Engineer zu behandeln, der bereits deinen ganzen Code gelesen hat. Du fragst „schreib eine Funktion zur Authentifizierung von Benutzern" und es schreibt etwas technisch Korrektes im Vakuum. Aber dein Projekt nutzt Supabase, nicht Firebase. Deine Tokens leben in httpOnly Cookies, nicht in localStorage. Dein Fehlerformat ist { status, message, data }, nicht das, worauf das Modell standardmäßig gesetzt ist.{ 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.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 jede nicht-triviale Anfrage ein. Ich mache das in Cursor, indem ich eine _context.md Datei im Projektstamm halte. Zwei Tastenanschläge zum Einfügen. Die Ausgabequalität springt merklich in die Höhe — weniger Annahmen, weniger Dinge, die ich rausreißen 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 nicht Namenskonventionen erfinden — don't let the model invent naming conventions
- Eingabetypen und Ausgabetypen — TypeScript Generics falls relevant — TypeScript generics if relevant
- Die Datenquelle — welche Tabelle, welcher API Endpoint, welche Cache-Schicht — which table, which API endpoint, which cache layer
- Edge Cases, die du bereits kennst — „handle the case where the array is empty" — "handle the case where the array is empty"
- Was du NICHT tun sollst — „don't use useEffect for this, use a server action" — "don't use useEffect for this, use a server action"
Das letzte Punkt ist wichtiger als die meisten Leute denken. Dem Modell zu sagen, was es vermeiden soll, spart enorme Zeit. Ich habe angefangen, eine kleine „Anti-Patterns"-Notiz pro Projekt zu führen — Dinge wie „no client components unless user interaction requires it" — und ich beziehe relevante Zeilen in Prompts für dieses Projekt ein.
---
Verkette deine Prompts. Frag nicht nach allem auf einmal.
Seahawk hatte Ende 2023 einen Fintech-Kunden — ich werde nicht sagen, wer — bei dem wir einen mehrstufigen KYC-Flow aufgebaut haben. Komplexes Zeug. Document Upload, Liveness-Check-Integration, Status-Polling. Ich machte früh den Fehler, GPT-4 zu bitten, „build the full KYC flow component" zu bauen. Es produzierte 600 Zeilen heroisch aussehender Müll. Verwirrte Logik, gemischte Concerns, keine echte Separation 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 aus dem verketteten Ansatz war brauchbar. Nicht perfekt — ich habe immer noch etwa 30 % umgeschrieben — aber brauchbar. Der monolithische Ansatz hat mir nichts gebracht.
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 hat drei Probleme gefunden, die es nicht berücksichtigt hatte. Eines davon war ein echtes Problem — eine Race Condition in einer asynchronen Schleife, die in der Produktion ein Albtraum zum Debuggen wäre.
Jetzt mache ich das routinemäßig. Schreibe den Code, dann bitte es, den Code zu kritisieren. Dann bitte es, die Kritik zu beheben. Es fühlt sich leicht absurd an — das Modell aufzufordern, seine eigene Arbeit zu überprüfen — aber es deckt konsequent Dinge auf, die ich nur 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 darfst als nötig für diesen Render — kein Over-Fetching. Schreib eine Supabase-Query für das Admin-Dashboard, 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."
Diese Rahmung macht zwei Dinge. Sie richtet die „Persona" des Modells auf das aus, was ich wirklich brauche. Und die Einschränkung funktioniert als Leitplanke — etwas, das das Modell explizit gegen sich 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 zeigt, dass 76% der Entwickler KI-Tools nutzen oder nutzen möchten — aber die gleichen Daten zeigten relativ geringes Vertrauen in die Genauigkeit. Diese Lücke zwischen Nutzung und Vertrauen ist genau dort, wo 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. Hat mir beim letzten großen Projekt wahrscheinlich sechs Stunden gespart — ein Headless-WooCommerce-Build für einen Einzelhändler, der von Shopify umzog. Ich habe einen Product-Query-Prompt (mit kleinen Änderungen) über vier verschiedene Komponenten hinweg wiederverwendet, statt den Kontext jedes Mal von Grund auf neu zu konstruieren.
Git-Track es. Ernsthaft. Prompt-Qualität ist reproduzierbar, wenn du Prompts als Artefakte statt als Wegwerf-Inputs behandelst. LangChains Prompt-Templates formalisieren 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, Kontextaufbau, Verkettung, Kritikschleifen — gelten für GPT-4, Claude 3.5 Sonnet, Gemini und whatever kommt als nächstes. Die Syntax unterscheidet sich etwas und einige Modelle reagieren besser auf bestimmte Formulierungen, aber die zugrunde liegende Logik bleibt erhalten. Ich habe festgestellt, dass Claude gut auf explizite Einschränkungen reagiert; GPT-4 reagiert gut auf Beispiele. Kleine Unterschiede, same fundamentals.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 mit jedem anderen Code auch. Wenn er in Production geht, wird er reviewed. Punkt. Ich habe aufgehört, bei Seahawk in PRs "das wurde von KI generiert" zu kennzeichnen, weil es zu einem Rotherrling wurde — Reviewer würden es anders prüfen, manchmal zu kritisch, manchmal nicht kritisch genug. Der Code beweist sich selbst oder nicht. Was ich kennzeichne: jede Stelle, wo die Logik nicht offensichtlich ist und ich keine Inline-Kommentare hinzugefügt habe, die die Überlegung erklären.
Verwendest du System Prompts oder nur Chat Prompts?
Beides. In Cursor setze ich auf die .cursorrules Datei für persistente Project-Level Instructions — 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 Wiederholungen sinnvoll reduziert und das Modell bleibt über eine lange Session 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?
Sie ersetzen bestimmte Aufgaben, nicht Developer. Die Urteilsfindungen — was zu bauen ist, wie man es architekturiert, welcher Trade-off zu dieser tatsächlichen Situation des Clients passt — die sind noch lange nicht automatisiert. Wenn überhaupt, sind es die Developer, die unter Druck geraten, die rein execution-orientiert waren, nicht design- oder architecture-orientiert. Schärfe die Urteilsschicht. 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.
