Back to all posts

Design-as-code: hur vi byggde om hela vår plattform på 12 dagar

Design-as-code: hur vi byggde om hela vår plattform på 12 dagar

En frontend-utvecklares syn på det nya produktutvecklingsflödet i AI-eran


Ett tal som inte borde vara möjligt

12 dagar. Två personer: en produktdesigner och en frontend-utvecklare. En komplett ombyggnad av plattformen.

Inte en prototyp. Inte en MVP. Ett fullständigt utbyte av en produktionsapplikation, som avslutades med en enda PR som tog bort 26,000 rader gammal kod. Varje sida, varje rutt, varje interaktion, byggdes om från grunden och levererades till riktiga användare.

I ett traditionellt produktutvecklingsflöde är denna tidslinje absurd. Ett projekt av denna omfattning skulle normalt ta månader: veckor av designutforskning i Figma, omgångar av intressentgranskning, en överlämningsceremoni, sprintplanering och sedan den långsamma processen med pixelperfekt implementation. Det som hände här var fundamentalt annorlunda. Inte för att vi arbetade hårdare, utan för att vårt sätt att samarbeta förändrades.

Det här är berättelsen om hur vi lanserade Zero-plattformen på VM0, och vad det lärde mig om framtiden för samarbete mellan produkt och engineering.

Den gamla flaskhalsen

Varje frontend-utvecklare känner till det traditionella flödet:

  1. Designer skapar mockups i Figma
  2. Designgranskning, iteration, godkännande
  3. Annoterade specifikationer med avstånd, färger, brytpunkter
  4. Utvecklare översätter visuella specifikationer till kod
  5. Fram och tillbaka: "Kan du flytta detta 4px till vänster?"
  6. Slutligen, koppla API-lagret
  7. Integrationstestning, mer fram och tillbaka

Flaskhalsen låg aldrig i ett enskilt steg. Den fanns i luckorna mellan stegen: väntan, översättningsförlust, kontextbyten. En designers mentala modell av en interaktion, när den väl plattats ut till en statisk Figma-ram och annoterats med röda linjer, når utvecklarens skrivbord redan försämrad. Utvecklaren bygger en version av det designern föreställt sig, men det blir oundvikligen en förlustfylld kopia.

Vi hade vant oss så mycket vid denna friktion att vi slutade se den. Det var bara "så här fungerar det".

Experimentet: Vad händer om designern levererar kod?

Den 5 mars 2026 öppnade Ming, vår produktdesigner, PR #3685: feat(platform): add zero app with shell, pages and polish. Den lade till 4,146 rader fungerande React-kod.

Inte en Figma-fil. Inte en export av designtokens. En körbar applikation.

PR:en innehöll ett komplett appskal: sidonavigation, ruttstruktur, sidmallar för chatt, schema, aktivitet, teamhantering och inställningar, allt stylat med vårt designsystem och renderat i webbläsaren. Datan var mockad, men gränssnittet var verkligt. Du kunde npm run dev och klicka dig igenom varje sida.

Ming skrev inte denna kod från grunden i traditionell mening. Hon använde AI-kodningsverktyg (först Cursor, senare Claude Code) för att översätta sin designvision direkt till React-komponenter. AI:n hanterade den mekaniska översättningen (JSX-struktur, CSS-egenskaper, komponentkomposition), medan Ming styrde de visuella och interaktiva besluten som ingen AI kan ta: rytmen i layouten, informationshierarkin, känslan i övergångarna.

Under de följande fyra dagarna landade tre PR:er till:

DatumPRVad Ming levererade
5 mars#3685Appskal, sidomeny, alla sidmallar (+4,146 rader)
6 mars#3825Schemasidor, UI-finslipning (+2,650 rader)
9 mars#3993Onboardingflöde, Slack-konfigurationsdialog (+1,146 rader)
9 mars#4050Om-sida, flytande navigeringskort

Den 9 mars fanns hela frontend-ytan av vår nya plattform som körbar kod. Varje sida du så småningom skulle se i produktion var redan klickbar i en utvecklingsmiljö. Den gjorde bara inget verkligt än.

Det var där jag kom in.

Mitt nya jobb: Ge själen liv

När jag öppnade kodbasen den 9 mars stod jag inte inför den vanliga utmaningen att översätta en platt design till kod. Koden fanns redan där. Mitt jobb var att ersätta varje mock med verklighet, att koppla varje vackert designad yta till den levande, pulserande backend under.

Det förändrade mitt arbete i grunden. Istället för att tänka på pixlar tänkte jag på dataflöden. Istället för att fråga "stämmer detta med mockupen?" frågade jag "vilket API-anrop behöver denna sida, och vad händer om det misslyckas?"

Så här såg min första vecka ut:

Dag 1 (9 mars): Autentisering och organisationsbyte. Jag kopplade Mings skal till Clerk-autentisering, lade till domänövergripande omdirigeringar och gjorde så att organisationsbytaren faktiskt bytte organisation. Två PR:er, båda mergade samma dag.

Dag 2 (10 mars): Connectors och schema. Jag ersatte det mockade connector-nätet med riktig API-data, kopplade schematabben till faktiska cron-jobb och kopplade instruktionredigeraren till backend. Fyra PR:er.

Dag 3 (11 mars): Den stora kopplingsdagen. Teamsidan fick riktig subagent-data (+3,271 rader). Aktivitetsidan fick riktiga loggar. Och kronan på verket: chattsidan kopplades till den faktiska agent-run-pipelinen, och ersatte ~1,200 rader demokod med ett fungerande AI-konversationsgränssnitt. Samma dag införde jag FeatureSwitchKey.Zero, en feature flag som lät oss köra gamla och nya plattformen sida vid sida.

Dag 4-5 (12-13 mars): Filbilagor, sessionshantering, multi-agent-chatt, inställningspersistens. Varje sida som Ming byggt gjorde nu verkligt arbete.

Rytmen var nästan musikalisk. Varje morgon valde jag en sida från Mings stomme, studerade dess komponentstruktur, identifierade vilken data den förväntade sig, byggde API-integrationen, hanterade fel, och pushade. På eftermiddagen var ytterligare en sida levande.

Feature-flaggen: Parallella världar

Feature-flaggen FeatureSwitchKey.Zero förtjänar ett eget omnämnande, för det var den som gjorde denna migrering säker istället för riskabel.

Från och med 11 mars körde vår produktionsapp två kompletta gränssnitt parallellt. Användare på det gamla systemet såg de gamla rutterna. Interna testare på det nya systemet såg Zero. Varje sida jag kopplade upp kunde testas i produktionskontext utan att riskera någon användares arbetsflöde.

Detta är inte revolutionerande. Feature-flaggor är standardpraxis. Men kombinationen av feature-flaggor och design-as-code-flödet skapade något speciellt: vi kunde validera hela användarupplevelsen för den nya plattformen (eftersom Ming byggt ett komplett, klickbart gränssnitt) samtidigt som vi successivt gjorde varje sida funktionell (eftersom jag kopplade dem en efter en). Om något gick fel kunde vi när som helst slå om tillbaka.

Inget gick fel.

Dag 12: Den stora omkopplaren

Den 17 mars öppnade jag PR #5095: refactor: remove all non-zero platform pages and feature flag.

Diffen: +456 rader, -26,041 rader.

Före: gamla VM0-plattformen. Tabeller, run-ID:n och rå sessionsdata.

Efter: nya Zero. Ett konversationsbaserat AI-arbetsutrymme med fästa agenter och användningskort.

I en enda merge togs alla gamla rutter bort. Feature-flaggen togs bort. Zero var inte längre ett alternativ; det var det enda läget. En uppföljande PR (#5155) tog bort /zero URL-prefixet helt: det som varit /zero/chat blev helt enkelt /chat.

Varför kände jag mig trygg med att göra detta klipp? För att:

  • Varje sida hade körts under feature-flaggen i minst 5 dagar
  • Varje API-integration hade testats mot produktionsdata
  • Gamla och nya systemen delade samma backend. Detta var ett frontend-byte, inte en datamigrering
  • Vi hade riktiga användare på det nya systemet som gav feedback hela tiden

De 26,000 raderna togs inte bort med ångest. De togs bort med lättnad.

Mönstret upprepas

Det som förvånade mig mest var inte själva migreringen. Det var att arbetsflödet vi upptäckt blev vårt standardläge för varje funktion därefter. Ming bygger UI-skalet med AI-hjälp, jag kopplar logiken och utökar arkitekturen. Samma design-as-code-mönster, i funktionsskala:

Behörighetssystem (19 mars → 7 april)

Ming levererade PR #5467, en behörighetslåda med Sheet-komponenter och växlingskontroller. Tre commits, rent UI.

Jag lade till 13 commits i samma PR: databas-migrering för firewall_access_requests, API-endpoints, integrationstester, lintfixar. Sedan, under de följande två veckorna, byggde 10+ uppföljande PR:er ut hela behörighetslagret: omdesign av godkännandekort, Slack-notiser för åtkomstförfrågningar, CLI doctor-kommandon för att diagnostisera behörighetsproblem och till slut bytte vi namn på hela konceptet från "firewall" till "permission" i kodbasen.

Mings låda var fröet. Behörighetssystemet blev trädet.

Schemasystem (23 mars → 13 april)

Ming designade schema-detaljrutten och kalenderupplevelsen (#6155). Tre commits med rent UI-arbete.

Jag lade till 14 commits: redigering av beskrivning med autogenerering, Slack-kanalval för notiser, dialoger för osparade ändringar, sammanslagning av kalender-/listvy och omfattande tester. Sedan byggde 15+ uppföljande PR:er ut det till ett komplett återkommande uppgiftssystem med körhistorik, tidszonshantering och cron-uttrycksstöd.

Telegram-integration (27 april → 28 april)

Vid det här laget var mönstret så inövat att vi levererade en hel plattformsintegration på 48 timmar. Ming byggde inställningsgränssnittet (#11196) och onboardingflödet (#11399). Jag byggde multi-bot-API, meddelandesändning/-mottagning, filuppladdning/-nedladdning, rik meddelandekontext, Ably realtidsuppdateringar och E2E-tester. Nästa dag var det aktiverat för alla användare.

Var AI passar in

Jag vill vara tydlig med AI:s roll här, för det är lätt att både över- och underskatta den.

AI gjorde det möjligt för designern att koda. Ming är produktdesigner, inte mjukvaruutvecklare. Hon tänker i layouter, hierarkier och interaktioner, inte i React-hooks och TypeScript-generics. AI-verktyg (Cursor, sedan Claude Code) överbryggade det gapet genom att hantera den mekaniska översättningen från designavsikt till fungerande kod. Ming styrde; AI skrev. Resultatet blev kod som en designer författat men en utvecklare kunde bygga vidare på.

AI snabbade upp granskningsloopen. Vid samarbets-PR:er granskade min AI-agent Mings kod, klassificerade problem efter prioritet (P0/P1/P2) och pushade fix-commits direkt. PR #5060 gick igenom fem granskningsrundor på 38 minuter. PR #5467 klarade tre rundor på 20 minuter. Detta är inte "AI ersätter kodgranskning". Jag läste fortfarande varje ändring. Men det mekaniska arbetet med att hitta lintproblem, saknade typer och testluckor automatiserades bort.

AI tog inte designbesluten. Informationsarkitekturen för varje sida, interaktionsmönstren, den visuella hierarkin: dessa kom från Mings produktkänsla, informerad av användarundersökningar och domänkunskap. AI kan generera en inställningssida, men kan inte avgöra vad som ska vara en växel kontra en dropdown, eller när en bekräftelsedialog behövs kontra när det är onödig friktion.

AI tog inte arkitekturbesluten. Beslutet att använda feature-flag för parallell utrullning, strategin för API-lagerseparation, beslutet att koppla sidor stegvis istället för allt på en gång: dessa var ingenjörsbeslut. AI hjälpte mig skriva koden snabbare, men sekvensering och riskhantering var mänskliga.

Den ärliga sammanfattningen: AI eliminerade översättningslagret mellan design och utveckling. Den ersatte inte någon disciplin; den tog bort gapet mellan dem.

Vad som förändrades i min roll

Efter tre månader i detta arbetsflöde ser jag min roll som frontend-utvecklare annorlunda.

Jag är inte längre en visuell översättare. Tiden då jag fick en Figma-fil och lade timmar på att matcha avståndsvärden är förbi. Inte för att jag blivit snabbare, utan för att det inte längre är mitt jobb. Designerns avsikt kommer som kod, inte som en bild av kod.

Jag är en arkitekturbyggare. Mitt främsta värde är att ta en fungerande UI-yta och bygga den osynliga infrastrukturen under: API-integrationer, datavalidering, felhantering, behörighetskontroller, realtidsuppdateringar, tester. Fördelningen på de flesta samarbets-PR:er säger allt. Ming bidrar med 3 UI-commits, jag bidrar med 13 commits för allt annat.

Jag är kvalitetsgrindvakt. Med AI-assisterade granskningsloopar kan jag upprätthålla kodkvalitet över en mycket större yta än tidigare. Den automatiserade granskningen fångar de mekaniska problemen; jag fokuserar på arkitektur, edge cases och att se till att funktionen verkligen fungerar från början till slut.

Jag är leveransstrateg. Feature-flaggor, stegvis koppling, parallella utrullningar: sekvenseringen av hur en funktion går från kod till produktion är nu en kärndel av mitt arbete, inte en eftertanke.

Siffrorna

Tre månader. Två personer. AI-assisterat hela vägen.

  • 914 mergade PR:er (679 mina, 235 Mings)
  • 12 dagar från första stomme till full plattformsersättning
  • 48 timmar för en komplett Telegram-integration (vår snabbaste funktion)
  • 26,000 rader borttagna i en enda säker merge
  • 88% av mina PR:er och 66% av Mings har AI-medförfattarskap

Detta är inga "hustle metrics". Ingen av oss jobbade helger eller drog all-nighters. Farten kommer av att dödtiden elimineras: överlämningsmöten, missförstånd om specifikationer, "kan du flytta detta 4px"-fram-och-tillbaka. När designavsikt går direkt in i kod, och utveckling bygger vidare på den koden direkt, blir det helt enkelt mindre slöseri.

Vad detta betyder för team

Jag påstår inte att alla team ska arbeta så här. Detta arbetsflöde växte fram ur vår specifika kontext: ett litet team, en grönfält-ombyggnad och tidig tillgång till kapabla AI-kodningsverktyg. Dina förutsättningar kan vara annorlunda.

Men jag tror att den underliggande förändringen är universell: gränsen mellan design och utveckling håller på att lösas upp, och AI är lösningsmedlet. När AI-verktyg blir bättre på att översätta avsikt till kod kommer fler designers att leverera kod direkt. Då kommer utvecklare att lägga mindre tid på översättning och mer på arkitektur, kvalitet och leverans.

Frontend-utvecklarens jobb försvinner inte. Det byter form. Och ärligt talat? Den nya formen är mer intressant.


Yuma är frontend-utvecklare på VM0, där han bygger plattformen som driver Zero, ett operativsystem för AI-agenter. Han har raderat mer gammal kod än han vill erkänna.

Stay in the loop

// Get the latest insights on AI teammates and collaboration.