Back to all posts

Design as Code: come abbiamo ricostruito l'intera piattaforma in 12 giorni

Il punto di vista di un frontend engineer sul nuovo workflow di product engineering nell'era dell'AI


Un numero che non dovrebbe avere senso

12 giorni. Due persone: un product designer e un frontend engineer. La ricostruzione completa di una piattaforma.

Non un prototipo. Non un MVP. La sostituzione integrale di un'applicazione in produzione, culminata in una singola PR che ha cancellato 26.000 righe di codice legacy. Ogni pagina, ogni route, ogni interazione, ricostruita da zero e rilasciata a utenti reali.

In qualsiasi workflow tradizionale di sviluppo prodotto, queste tempistiche sono assurde. Un progetto di questa portata richiederebbe normalmente mesi: settimane di esplorazione di design in Figma, cicli di revisione con gli stakeholder, una cerimonia di handoff, lo sprint planning e poi la lenta fatica di un'implementazione pixel-perfect. Quello che è successo qui è stato qualcosa di fondamentalmente diverso. Non perché abbiamo lavorato di più, ma perché è cambiato il modo in cui lavoriamo insieme.

Questa è la storia di come abbiamo rilasciato la piattaforma Zero in VM0, e di ciò che mi ha insegnato sul futuro della collaborazione tra product e engineering.

Il vecchio collo di bottiglia

Ogni frontend engineer conosce la pipeline tradizionale:

  1. Il designer crea i mockup in Figma
  2. Revisione del design, iterazione, approvazione
  3. Specifiche annotate con spaziature, colori, breakpoint
  4. L'engineer traduce le specifiche visive in codice
  5. Avanti e indietro: "Puoi spostare questo di 4px a sinistra?"
  6. Finalmente, si collega il layer delle API
  7. Test di integrazione, ancora avanti e indietro

Prima e dopo: il vecchio workflow basato sull'handoff vs. la nuova collaborazione diretta

Il collo di bottiglia non era mai in un singolo passaggio. Era negli spazi tra i passaggi: le attese, la perdita nella traduzione, il continuo cambio di contesto. Il modello mentale che un designer ha di un'interazione, una volta appiattito in un frame statico di Figma e annotato con i redline, arriva sulla scrivania dell'engineer già degradato. L'engineer ricostruisce una versione di ciò che il designer aveva immaginato, ma è inevitabilmente una copia con delle perdite.

Ci eravamo talmente abituati a questo attrito che avevamo smesso di notarlo. Era semplicemente "come funzionano le cose".

L'esperimento: e se fosse il designer a scrivere il codice?

Il 5 marzo 2026, Ming, la nostra product designer, ha aperto la PR #3685: feat(platform): add zero app with shell, pages and polish. Aggiungeva 4.146 righe di codice React funzionante.

Non un file Figma. Non un export di design token. Un'applicazione funzionante.

La PR conteneva uno shell completo dell'app: navigazione nella sidebar, struttura del routing, scheletri di pagina per chat, schedule, attività, gestione del team e impostazioni, tutti realizzati con il nostro design system, tutti renderizzati nel browser. I dati erano mock, ma l'interfaccia era reale. Potevi lanciare npm run dev e cliccare attraverso ogni pagina.

Ming non ha scritto questo codice da zero nel senso tradizionale. Ha usato strumenti di coding AI (prima Cursor, poi Claude Code) per tradurre la sua visione di design direttamente in componenti React. L'AI si è occupata della traduzione meccanica (struttura JSX, proprietà CSS, composizione dei componenti), mentre Ming guidava le decisioni visive e di interazione che nessuna AI può prendere: il ritmo del layout, la gerarchia delle informazioni, la sensazione delle transizioni.

Nei quattro giorni successivi sono arrivate altre tre PR:

DataPRCosa ha rilasciato Ming
5 mar#3685Shell dell'app, sidebar, tutti gli scheletri di pagina (+4.146 righe)
6 mar#3825Pagine schedule, rifinitura UI (+2.650 righe)
9 mar#3993Flusso di onboarding, dialog di configurazione Slack (+1.146 righe)
9 mar#4050Pagina About, card di navigazione fluttuante

Entro il 9 marzo, l'intera superficie frontend della nostra nuova piattaforma esisteva come codice funzionante. Ogni pagina che avresti poi visto in produzione era già cliccabile in un ambiente di sviluppo. Semplicemente non faceva ancora nulla di reale.

Ed è qui che sono entrato in scena io.

Il mio nuovo lavoro: iniettare l'anima

La migrazione in 12 giorni: i blocchi di UI posizionati, la logica collegata, il grande switch attivato

Quando ho aperto il codebase il 9 marzo, non mi sono trovato davanti alla solita sfida di tradurre un design piatto in codice. Il codice era già lì. Il mio compito era sostituire ogni mock con la realtà, collegare ogni superficie disegnata splendidamente al backend vivo e pulsante che stava sotto.

Questo ha cambiato il mio lavoro in modo fondamentale. Invece di pensare ai pixel, pensavo ai flussi di dati. Invece di chiedermi "corrisponde al mockup?", mi chiedevo "di quale chiamata API ha bisogno questa pagina, e cosa succede se fallisce?"

Ecco com'è stata la mia prima settimana:

Giorno 1 (9 marzo): Autenticazione e cambio di organizzazione. Ho collegato lo shell di Ming all'autenticazione Clerk, ho aggiunto i redirect cross-domain e ho fatto in modo che il selettore di organizzazione cambiasse davvero organizzazione. Due PR, entrambe mergiate lo stesso giorno.

Giorno 2 (10 marzo): Connettori e schedule. Ho sostituito la griglia mock dei connettori con dati API reali, ho collegato la tab schedule a cron job effettivi e ho connesso l'editor delle istruzioni al backend. Quattro PR.

Giorno 3 (11 marzo): Il grande giorno del wiring. La pagina del team ha ricevuto dati reali dei subagent (+3.271 righe). La pagina attività ha ricevuto log reali. E il gioiello della corona: la pagina chat è stata connessa alla vera pipeline di esecuzione degli agenti, sostituendo circa 1.200 righe di codice demo con un'interfaccia di conversazione AI funzionante. Quello stesso giorno ho introdotto FeatureSwitchKey.Zero, un feature flag che ci permetteva di far girare la vecchia e la nuova piattaforma fianco a fianco.

Giorni 4-5 (12-13 marzo): Allegati di file, gestione delle sessioni, chat multi-agente, persistenza delle impostazioni. Ogni pagina che Ming aveva costruito stava ora svolgendo un lavoro reale.

Il ritmo era quasi musicale. Ogni mattina sceglievo una pagina dallo scaffold di Ming, ne studiavo la struttura dei componenti, identificavo quali dati si aspettava, costruivo l'integrazione API, gestivo gli stati di errore e facevo push. Entro il pomeriggio, un'altra pagina prendeva vita.

Il feature switch: mondi paralleli

Il feature flag FeatureSwitchKey.Zero merita una menzione a parte, perché è ciò che ha reso questa migrazione sicura anziché avventata.

Dall'11 marzo in poi, la nostra app in produzione faceva girare due interfacce complete in parallelo. Gli utenti sul vecchio sistema vedevano le vecchie route. I tester interni sul nuovo sistema vedevano Zero. Ogni pagina che collegavo poteva essere testata nel contesto di produzione senza mettere a rischio il workflow di un singolo utente.

Non è una cosa rivoluzionaria. I feature flag sono una pratica standard. Ma la combinazione di feature flag con il workflow design-as-code ha creato qualcosa di speciale: potevamo validare l'intera UX della nuova piattaforma (perché Ming aveva costruito un'interfaccia completa e navigabile) mentre rendevamo progressivamente funzionale ogni pagina (perché le collegavo una alla volta). In qualsiasi momento, se qualcosa fosse andato storto, avremmo potuto riportare indietro lo switch.

Non è andato storto nulla.

Giorno 12: il grande switch

Il 17 marzo ho aperto la PR #5095: refactor: remove all non-zero platform pages and feature flag.

Il diff: +456 righe, -26.041 righe.

Prima: la vecchia VM0 Platform. Tabelle, ID di esecuzione e dati di sessione grezzi.

La vecchia VM0 Platform

Dopo: la nuova Zero. Uno spazio di lavoro AI conversazionale con agenti fissati e card dei casi d'uso.

La nuova piattaforma Zero

In un singolo merge, ogni route legacy è stata cancellata. Il feature flag è stato rimosso. Zero non era più un'opzione; era l'unica modalità. Una PR successiva (#5155) ha eliminato del tutto il prefisso URL /zero: ciò che era /zero/chat è diventato semplicemente /chat.

Perché mi sono sentito sicuro nel fare questo taglio? Perché:

Le 26.000 righe non sono state cancellate con ansia. Sono state cancellate con sollievo.

Lo schema si ripete

Ciò che mi ha sorpreso di più non è stata la migrazione in sé. È stato il fatto che il workflow che avevamo scoperto è diventato la nostra modalità predefinita per ogni feature successiva. Ming costruisce lo shell dell'interfaccia con l'assistenza dell'AI, io collego la logica ed estendo l'architettura. Lo stesso schema design-as-code, ma a livello di feature:

Sistema dei permessi (19 marzo → 7 aprile)

Ming ha rilasciato la PR #5467, un'interfaccia a drawer per i permessi con componenti Sheet e controlli a toggle. Tre commit, UI pulita.

Io ho aggiunto 13 commit alla stessa PR: migrazione del database per firewall_access_requests, endpoint API, test di integrazione, correzioni di lint. Poi, nelle due settimane successive, oltre 10 PR di follow-up hanno costruito l'intero layer dei permessi: ridisegno della card di approvazione, notifiche Slack per le richieste di accesso, comandi doctor della CLI per diagnosticare problemi di permessi e, infine, la rinomina dell'intero concetto da "firewall" a "permission" in tutto il codebase.

Il drawer di Ming era il seme. Il sistema dei permessi era l'albero.

Sistema di schedule (23 marzo → 13 aprile)

Ming ha progettato la route di dettaglio dello schedule e la UX del calendario (#6155). Tre commit di lavoro UI pulito.

Io ho aggiunto 14 commit: modifica della descrizione con generazione automatica, selezione del canale Slack per le notifiche, dialog di conferma per le modifiche non salvate, unificazione delle viste calendario/lista e test completi. Poi oltre 15 PR di follow-up l'hanno espanso in un sistema completo di task ricorrenti con cronologia delle esecuzioni, gestione dei fusi orari e supporto per le espressioni cron.

Integrazione Telegram (27 aprile → 28 aprile)

A questo punto, lo schema era così collaudato che abbiamo rilasciato un'intera integrazione di piattaforma in 48 ore. Ming ha costruito la UI delle impostazioni (#11196) e il flusso di onboarding (#11399). Io ho costruito l'API multi-bot, l'invio e la ricezione dei messaggi, l'upload e il download dei file, il contesto dei messaggi avanzato, gli aggiornamenti in tempo reale con Ably e i test E2E. Il giorno dopo, era abilitata per tutti gli utenti.

Dove si inserisce l'AI

Voglio essere preciso sul ruolo dell'AI in tutto questo, perché è facile sopravvalutarlo o sottovalutarlo.

L'AI ha permesso al designer di scrivere codice. Ming è una product designer, non una software engineer. Pensa in termini di layout, gerarchie e interazioni, non di React hook e generics di TypeScript. Gli strumenti AI (Cursor, poi Claude Code) hanno colmato quel divario occupandosi della traduzione meccanica dall'intento di design al codice funzionante. Ming guidava; l'AI scriveva. Il risultato era codice scritto da una designer ma su cui un engineer poteva costruire.

L'AI ha accelerato il ciclo di revisione. Sulle PR collaborative, il mio agente AI revisionava il codice di Ming, classificava i problemi per priorità (P0/P1/P2) e faceva push delle correzioni direttamente. La PR #5060 ha attraversato cinque cicli di revisione in 38 minuti. La PR #5467 ne ha completati tre in 20 minuti. Questo non significa "l'AI che sostituisce la code review". Leggo ancora ogni modifica. Ma il lavoro meccanico di identificare problemi di lint, tipi mancanti e lacune nei test è stato automatizzato.

L'AI non ha preso le decisioni di design. L'architettura informativa di ogni pagina, i pattern di interazione, la gerarchia visiva: queste sono nate dall'istinto di prodotto di Ming, informato dalla user research e dall'esperienza nel dominio. L'AI può generare una pagina di impostazioni, ma non può decidere cosa debba essere un toggle anziché un dropdown, o quando un dialog di conferma sia giustificato anziché un attrito.

L'AI non ha preso le decisioni di architettura. La scelta di usare un feature flag per il deploy in parallelo, la strategia di separazione del layer API, la decisione di collegare le pagine in modo incrementale anziché tutte insieme: queste sono state scelte di giudizio ingegneristico. L'AI mi ha aiutato a scrivere il codice più velocemente, ma la sequenza e la gestione del rischio sono state umane.

Il riassunto onesto: l'AI ha eliminato il layer di traduzione tra design ed engineering. Non ha sostituito nessuna delle due discipline; ha rimosso il divario tra loro.

Cosa è cambiato nel mio ruolo

Dopo aver vissuto in questo workflow per tre mesi, vedo il mio ruolo di frontend engineer in modo diverso.

Non sono più un traduttore visivo. I giorni in cui ricevevo un file Figma e passavo ore a far combaciare i valori di spaziatura sono finiti. Non perché io sia più veloce, ma perché non è più il mio lavoro. L'intento del designer arriva come codice, non come un'immagine del codice.

Sono un estensore di architettura. Il mio valore principale sta nel prendere una superficie UI funzionante e costruire l'infrastruttura invisibile sottostante: integrazioni API, validazione dei dati, gestione degli errori, controlli dei permessi, aggiornamenti in tempo reale, test. Il rapporto sulla maggior parte delle PR collaborative racconta la storia. Ming contribuisce con 3 commit di UI, io contribuisco con 13 commit di tutto il resto.

Sono un guardiano della qualità. Con i cicli di revisione assistiti dall'AI, posso mantenere la qualità del codice su una superficie molto più ampia di prima. La revisione automatizzata coglie i problemi meccanici; io mi concentro sulle questioni architetturali, sui casi limite e sull'assicurarmi che la feature funzioni davvero end-to-end.

Sono uno stratega della delivery. Feature flag, wiring incrementale, deploy in parallelo: la sequenza con cui una feature passa dal codice alla produzione è ora una parte centrale del mio lavoro, non un ripensamento.

I numeri

Tre mesi. Due persone. Assistiti dall'AI per tutto il tempo.

Non sono metriche da "spremersi al massimo". Nessuno di noi due ha lavorato nei weekend o ha fatto nottate. La velocità arriva dall'eliminazione dei tempi morti: le riunioni di handoff, i fraintendimenti sulle specifiche, l'avanti e indietro del "puoi spostare questo di 4px". Quando l'intento di design fluisce direttamente nel codice, e l'engineering estende quel codice sul posto, c'è semplicemente meno spreco.

Cosa significa questo per i team

Non sto sostenendo che ogni team debba lavorare in questo modo. Questo workflow è emerso dal nostro contesto specifico: un team piccolo, un'opportunità di ricostruzione greenfield e l'accesso anticipato a strumenti di coding AI capaci. I risultati possono variare.

Ma credo davvero che il cambiamento di fondo sia universale: il confine tra design ed engineering si sta dissolvendo, e l'AI è il solvente. Man mano che gli strumenti AI diventano migliori nel tradurre l'intento in codice, sempre più designer scriveranno codice direttamente. Quando questo accadrà, gli engineer passeranno meno tempo sulla traduzione e più tempo sull'architettura, sulla qualità e sulla delivery.

Il lavoro del frontend engineer non sta scomparendo. Sta cambiando forma. E sinceramente? La nuova forma è più interessante.


Yuma è un frontend engineer in VM0, dove costruisce la piattaforma che alimenta Zero, un sistema operativo per agenti AI. Ha cancellato in massa più codice legacy di quanto vorrebbe ammettere.

Related Articles

Stay in the loop

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

SubscribeJoin Discord