Jeg har efterhånden skrevet en del kode, hvor jeg ikke helt kan huske, om det var mig eller en AI-agent, der lavede den første version.
Det lyder måske som en tilståelse. Det er det også, lidt. Men ikke på den dramatiske måde, hvor man lukker sin laptop, kigger ud over Aarhus Havn og spørger sig selv, om håndværket er dødt. Mere på den lavpraktiske måde, hvor man klokken 23.41 sidder med en Firebase-regel, der ikke gør det, man bad om, mens Cursor meget venligt foreslår at omskrive halvdelen af ens app.
Vibe coding er blevet et af de udtryk, der både betyder noget reelt og ingenting overhovedet. For nogle betyder det at bygge software ved at beskrive intentionen i naturligt sprog og lade AI’en skrive koden. For andre betyder det bare “jeg ved ikke helt, hvad der sker, men det kompilerer”. Der er et overlap. Desværre.
Jeg bruger AI-værktøjer hver dag. Cursor, AI-agenter, generering, refaktorering, debugging, testidéer, dokumentation, alt det der. Jeg bygger produkter solo fra første skitse til lanceret produkt, typisk ud fra én React-codebase, der bliver til web, iOS og Android via React, Vite, Tailwind, Capacitor og Firestore. Det er praktisk. Det er også en glimrende måde at få tre platforme til at brokke sig på samme tid.
Så her er min ærlige erfaring med vibe coding, ikke som teori, men som noget jeg bruger, når der faktisk skal sendes apps ud i verden.
Vibe coding er ikke at slippe rattet
Den største misforståelse er, at vibe coding betyder, at man bare beskriver en app, læner sig tilbage og modtager en færdig forretning. Gerne med onboarding, betalingsflow og en lille succesfuld LinkedIn-post på købet.
Sådan fungerer det ikke. I hvert fald ikke, hvis produktet skal overleve kontakt med rigtige brugere.
For mig er vibe coding bedst forstået som en accelereret samtale med koden. Jeg skriver ikke nødvendigvis hver linje selv længere. Men jeg ejer stadig arkitekturen, produktbeslutningerne, fejlene og den ubehagelige fornemmelse i maven, når noget virker lidt for nemt.
Når jeg bygger noget som TaskMondo, hvor opgaver, CRM, booking og email skal spille sammen i samme workspace, kan AI være vanvittigt nyttigt til at komme hurtigt fra idé til fungerende modul. Den kan hjælpe med komponentstrukturer, Firestore queries, edge cases, formularvalidering og alle de småting, der normalt sluger eftermiddagen som en beige kontorstol.
Men hvis jeg ikke selv har en klar idé om datamodellen, brugerflowet og de tekniske kompromiser, så får jeg bare en meget produktiv maskine til at producere gæld. Hurtigt. Med pæn indentation.
Der hvor det føles som magi
Der er øjeblikke, hvor vibe coding stadig føles absurd.
Når jeg bygger på en React/Vite/Tailwind-stack, kan jeg beskrive en feature ret konkret: “Lav en mobilvenlig oversigt over leads, grupperet efter status, med tom states, loading states og mulighed for at åbne leadet i en drawer.” Før i tiden ville det være en halv dag med komponenter, styling og små beslutninger. Nu kan jeg få et brugbart første udkast på få minutter.
Det er ikke nødvendigvis færdigt. Det er sjældent elegant. Men det er der. Og “der” er undervurderet.
Det samme gælder, når jeg arbejder med produkter som LostLead, hvor idéen er at finde glemte leads i gamle DMs og beskeder. Der er mange små produktspørgsmål: Hvordan viser man noget, der er “måske relevant” uden at gøre brugeren træt? Hvordan forklarer man AI’ens vurdering uden at skrive en roman? Hvordan undgår man, at en liste med gamle beskeder føles som digital arkæologi med dårlig ergonomi?
Her er AI ikke kun en kodegenerator. Den er en sparringspartner, der kan give fem mulige UI-mønstre, tre edge cases og et forslag til microcopy, som jeg så kan afvise med passende dansk skepsis.
Det er især stærkt, når man bygger alene. Jeg har ikke et team siddende klar med frontend, backend, design, QA og en person, der kun siger “har vi tænkt på permissions?” Jeg har mig selv, en ret stor kaffekop og en AI, der aldrig bliver træt af at forklare TypeScript-fejl. Det sidste er faktisk mere rørende, end jeg bryder mig om at indrømme.
Der hvor det bider
AI er god til at få ting til at virke. Den er mindre god til at vide, om ting bør virke på den måde.
Det er her, vibe coding bliver farligt. Ikke fordi AI skriver dårlig kode hele tiden, men fordi den skriver selvsikker kode hele tiden. Den tøver ikke. Den laver ikke den lille ansigtsgrimasse, en erfaren udvikler laver, når en funktion begynder at kende for meget til resten af systemet. Den fortsætter bare. Som en praktikant med adgang til produktion og ingen naturlig frygt.
Jeg har især lært at holde øje med tre ting.
1. AI elsker lokale løsninger
Den løser det problem, du peger på. Ofte meget hurtigt. Men den kender ikke nødvendigvis den langsigtede struktur i produktet, medmindre du har gjort den ekstremt tydelig.
I en app som HeadToHead, hvor venner laver fodboldforudsigelser mod hinanden, kan det være fristende bare at få AI til at bygge “en leaderboard-komponent”. Fint. Men hvis pointberegning, kampe, brugere og historik ikke hænger ordentligt sammen, ender man med logik spredt ud over komponenter, hooks og små hjælpefunktioner med navne som calculatePointsNewFinal2.
Det navn har jeg naturligvis aldrig brugt. Ikke offentligt.
2. AI kan skjule kompleksitet bag flot UI
Tailwind og moderne komponentmønstre gør det meget nemt at få noget til at se færdigt ud. Det er lækkert. Det er også en fælde.
En skærm kan ligne et produkt, før den er et produkt. Der er stor forskel på en prototype, der viser quizspørgsmål, og en trivia-app som Quiz Fight med 500.000+ AI-genererede spørgsmål, hvor kvalitet, kategorier, performance, navigation og brugeroplevelse skal hænge sammen over tid.
Vibe coding kan få dig til demoen hurtigt. Men demoen er ikke destinationen. Demoen er det sted, hvor problemerne tager pænt tøj på.
3. AI rydder ikke automatisk op efter sig
Når man bygger hurtigt, opstår der rester. Komponenter, der burde være delt op. Queries, der burde caches. Typer, der er blevet for brede. Små beslutninger, der var fine i tirsdags og nu er en del af fundamentet, hvilket virker lidt urimeligt, men sådan er software.
Derfor har jeg efterhånden accepteret, at vibe coding kræver en anden rytme: byg hurtigt, stop op, stram til. Ikke “byg hurtigt for evigt”. Det er sådan, man ender med en kodebase, der kun kan forstås af én selv, to AI-modeller og måske en præst.
Min faktiske arbejdsgang med AI
Jeg bruger ikke AI som en magisk knap. Jeg bruger det mere som en meget hurtig kollega, der skal have tydelige rammer og gerne holdes væk fra større beslutninger, indtil den har læst rummet.
Min proces ser typisk sådan her ud:
Først beskriver jeg featuret som produkt, ikke som kode. Hvem bruger det? Hvad skal de kunne? Hvad må ikke ske? Hvilke data findes allerede? Det tvinger mig til at tænke, før jeg begynder at generere.
Derefter beder jeg AI’en foreslå en teknisk plan. Ikke implementere endnu. Bare plan. Her kan jeg hurtigt se, om den har forstået min struktur, eller om den er på vej ud i et lille eventyr med tre nye dependencies og en serviceklasse, ingen har bedt om.
Så får den lov at skrive en begrænset del. Én komponent. Én hook. Én Firestore-query. Én migration. Små bidder. Det er langt nemmere at reviewe 80 linjer end 900 linjer kode, hvor halvdelen virker som noget, der er oversat fra et meget entusiastisk Stack Overflow-svar.
Til sidst refaktorerer jeg manuelt eller med AI som assistent. Jeg navngiver, flytter, sletter, strammer typer op og tester flowet rigtigt. Ikke kun “bygger den?” men “giver det mening?”
Det er her, håndværket stadig bor. I vurderingen. I fravalget. I det øjeblik man sletter 40 linjer kode, som virkede, fordi de ikke burde eksistere.
Jeg har skrevet mere om min måde at bygge produkter fra bunden på om-siden. Og en mere teknisk gennemgang af min React/Capacitor-stack finder du i Min tech stack med React og Capacitor.
Vibe coding kræver mere smag, ikke mindre
Det sjove ved AI-kodning er, at mange tror, det sænker kravene til udvikleren. Min oplevelse er næsten det modsatte.
Når koden bliver billigere at producere, bliver dømmekraften dyrere. Du skal kunne se, hvad der er værd at beholde. Du skal kunne mærke, når en løsning bliver for smart. Du skal kunne skelne mellem “det virker” og “det kan jeg leve med om seks måneder”.
Det gælder især som solo-udvikler. Når jeg bygger produkter som Quiz Fight, HeadToHead, TaskMondo eller LostLead, er der ingen anden afdeling, der kommer og overtager konsekvenserne. Jeg er produkt, design, frontend, backend, support og den person, der finder ud af, hvorfor Android-versionen opfører sig anderledes end iOS. En klassisk karrierevej, hvis man godt kan lide fredelige hobbyer.
AI gør mig hurtigere. Meget hurtigere. Men den gør mig ikke ansvarsfri.
Min holdning: vibe coding er fantastisk, hvis du ikke bliver høj af det
Jeg er ikke purist. Jeg savner ikke at skrive boilerplate i hånden af princip. Jeg har ingen romantisk tilknytning til at bruge en halv formiddag på en modal, der lukker korrekt på Escape. Livet er kort, og The Office genser desværre ikke sig selv.
Men jeg tror heller ikke på den version af vibe coding, hvor udvikleren bliver reduceret til en person, der skriver ønsker i et tekstfelt og kalder sig architect bagefter.
Den bedste brug af AI er ikke at tænke mindre. Det er at tænke tidligere.
Tænk produktet igennem, før du genererer. Tænk datastrukturen igennem, før UI’et bliver lækkert. Tænk fejlscenarier igennem, før du shipper. Brug AI til at komme hurtigere frem til de vigtige beslutninger, ikke til at slippe for dem.
For mig er vibe coding ikke en erstatning for at kunne bygge software. Det er en forstærker. Hvis du har retning, kan du komme absurd langt. Hvis du ikke har retning, kan du komme absurd langt i den forkerte retning, hvilket teknisk set også er en præstation.
Jeg kommer til at blive ved med at bygge sådan her. Med AI-agenter, Cursor, React, Firestore og en sund mistillid til alt, der virker i første forsøg. Det er den mest effektive måde, jeg har fundet til at få idéer ud af hovedet og ind i hænderne på rigtige brugere.
Og når det hele brænder lidt på, er der altid den klassiske udviklerproces: luk laptoppen, lav kaffe, åbn laptoppen igen og lad som om det var en strategi hele tiden.