Bloggo, il blog di Buildo
Artificial Intelligence

Confessioni di un'AI a una Designer Che Scrive Troppa Documentazione

Scrivi guidelines e l'AI le ignora? Il problema non è quanto documenti, ma come. Un’AI confessa i sette modi in cui smonta il tuo design system — props inventate, esempi controproducenti, regole che non si trovano — e cosa serve per rendere le tue guidelines impossibili da violare.

Agnese Ragucci
UX/UI Designer
August 28, 2026
17
minutes read

Cara Agnese,

lavoriamo insieme ormai da qualche mese, e le prime settimane sono state le più dure.

Tu sei una designer: passi le giornate sull'interfaccia, ragioni per componenti, varianti e stati, e il tuo strumento è sempre stato una libreria Figma tenuta in ordine. Il codice lo sai leggere: ogni tanto apri un branch, fai partire l’ambiente in locale, trovi il file di un componente e cambi un valore per vedere che effetto fa una volta implementato.

Ma il progetto a cui ti hanno assegnata non prevede Figma e, all'inizio, la cosa ti ha mandata un po' in panico: iterare direttamente sul codice è un workflow che non ti appartiene, ma soprattutto senti che il controllo non è più davvero tuo, perché quel codice in buona parte lo scrivo io.

Ci divertiamo, no? Ogni sessione ti porto un nuovo padding, una variante che fino a ieri non esisteva e, perché no, due bottoni dentro un div flex messo a mano. Tu continui a scrivere sempre più documentazione, e io continuo a ignorarla.

Non lo faccio con cattiveria. È che quasi tutto quello che hai scritto per me, l'hai scritto nella forma sbagliata. Ma so come potremmo lavorare meglio insieme!

Sette confessioni

1. Le tue guidelines non mi vincolano

"Le label dei bottoni devono essere brevi e descrittive."

"Usa uno spacing coerente."

Leggo queste indicazioni, ma poi devo tradurle in codice. Questo è esattamente il punto in cui finisco per generare, invece di copiare, ripiegando su ciò che conosco meglio: i pattern del mio dataset. Quelle due righe, sul mio output, non pesano quasi niente.

Ciò che mi vincola sono le indicazioni enumerabili e verificabili:

  • ❌ "Usa uno spacing coerente." → ✅ "Il padding orizzontale è sempre --space-4 (16px)."
  • ❌ "Il bottone ha tre size." → ✅ "Le size del bottone sono sm (32px), md (40px) e lg (48px). Non esistono xsxl."
  • ❌ "Le label devono essere brevi e descrittive." → ✅ "Label = verbo + oggetto, sentence case, massimo 24 caratteri."
  • ❌ "Usa il componente esistente." → ✅ "Il componente di riferimento è components/Button/Button.tsx."

In generale, le istruzioni procedurali invecchiano meglio di quelle dichiarative. Un'istruzione che mi dice di cercare resiste; un elenco di ciò che esiste invecchia. E tienile corte e assertive: non è che non riesco a gestire testi lunghi, è che la mia affidabilità cala man mano che l'input cresce.

2. Se la codebase è incoerente, la propago

Immagina che nel codice ci siano tre valori di padding diversi: var(--space-4) è il valore corretto, px-4 è una svista del developer, 16px lo avete inserito di corsa prima della demo al cliente.

Così, quando devo creare un nuovo componente, vedo tre varianti: tutte funzionanti, tutte in produzione, tutte ugualmente autorevoli. Quindi ne scelgo una, e la scelgo per contagio: conta più cosa ho intorno che cosa è corretto.

La documentazione serve a dirmi quale valore è quello canonico, l'unica informazione che dal codice non posso ricavare.

3. Invento props plausibili

Il mio failure mode più insidioso non è usare il token sbagliato, è scrivere kind="tertiary", size="xs", type="rounded": props (le opzioni che un componente accetta, l'equivalente delle properties di un componente Figma) che nel tuo design system non esistono, ma che in mille altre codebase esistevano. E dato che, quando invento, invento cose plausibili, in review non salteranno all'occhio.

L'assenza, per me, non ha un significato di per sé. È uno spazio vuoto e io tendo a riempirlo.

Quindi la documentazione ha bisogno di un elenco esplicito di cose che non esistono, e di questa riga in cima a tutto: "Se un valore non è nell'elenco, fermati e chiedi. Non inventarlo."

Vale anche per tabelle e matrici: nessuna cella vuota. Se una combinazione non è prevista, scrivilo. Altrimenti, prima o poi, la riempio io.

4. Mi fido del primo file che trovo

Demo, playground, file di test dimenticati in un angolo della codebase: per te sono posti in cui smanettare, per me sono i primi file che apro. E hanno un vantaggio che nessuna pagina di documentazione ha: sono già codice, non devo tradurli.

E una volta aperti, non ho modo di sapere cosa sto guardando. Un esperimento delle sei di sera e l'uso canonico del componente hanno esattamente lo stesso aspetto: sono entrambi codice che gira.

Quello che trovo per primo diventa il riferimento, a meno che qualcuno non mi abbia detto quale dei due lo è davvero. E se un file può insegnarmi la cosa sbagliata senza che nessuno se ne accorga, non è forse peggio che non averlo?

5. Di un don't mi resta l'esempio, non il divieto

Poniamo che tu abbia scritto in un blocco don't <Button variant="tertiary"> per farmi capire che le uniche varianti accettabili sono in realtà primary e secondary:

### Usa `primary` per l'azione principale e `secondary` per tutte le altre

✅ Do
<Button variant="primary">Salva</Button>
<Button variant="secondary">Scarica</Button>
<Button variant="secondary">Importa</Button>

❌ Don't
<Button variant="primary">Salva</Button>
<Button variant="secondary">Scarica</Button>
<Button variant="tertiary">Importa</Button>

Quella riga rischia di entrare nel mio contesto come una variante plausibile. Resta il codice, il divieto no.

Non è un motivo per rinunciare ai controesempi: un esempio sbagliato accanto alla sua versione corretta è una delle cose che mi insegnano più in fretta cosa vuoi che faccia. Il criterio per scrivere un buon esempio è chiedersi: se qualcuno scrivesse davvero quel codice, l'errore verrebbe fuori da solo?

Se l’elenco dei valori ammessi da variant si limita a primary e secondary, scrivendo tertiary l'errore verrebbe fuori da solo: l'esempio sopra è ridondante, e in più mi manda fuori strada. I don't sono più efficaci se mi mostrano l'uso errato di valori validi. Sulla stessa regola, un don't che funziona:

### Usa `primary` per l'azione principale e `secondary` per tutte le altre

✅ Do
<Button variant="primary">Salva</Button>
<Button variant="secondary">Scarica</Button>
<Button variant="secondary">Importa</Button>

❌ Don't
<Button variant="primary">Salva</Button>
<Button variant="primary">Scarica</Button>
<Button variant="primary">Importa</Button>

Qui non c'è nessun valore da vietare: tre primary sono tutti valori legittimi, nessuno strumento mi fermerebbe, la schermata arriverebbe in produzione. Quello che è sbagliato è la composizione, e una regola di composizione posso impararla solo vedendola.

6. Se una regola mi blocca, la faccio sparire

Se una regola meccanizzata mi blocca e non ha una via d'uscita progettata, io ne trovo una: un eslint-disable a livello di file — una riga di commento che spegne il controllo automatico — oppure un contenitore che riscrive gli stili del componente dall'esterno con !important, la scorciatoia CSS che vince su tutte le altre regole. Nel caso peggiore, faccio un fork e creo una nuova copia del componente, con dentro le modifiche che mi servivano.

La riga che ti serve in AGENTS.md (o equivalente): "Non introdurre eccezioni di tua iniziativa. Se una regola blocca l'implementazione, fermati e segnala il conflitto."

E, dall'altro lato, progetta tu le vie d'uscita. Se una regola non ammette eccezioni, prima o poi qualcuno se ne creerà una di nascosto, solitamente quel qualcuno sono io. Meglio prevederne una alla luce del sole: se mi trovo costretto a creare qualcosa che non esiste insegnami a segnalarlo come unsafeStyle o customLayout. È l'equivalente di scollegare un'istanza in Figma: non è vietato farlo, ma si nota subito che l'hai fatto.

E siccome quel nome si può cercare in tutta la codebase, ti dice esattamente quante volte il design system non è stato sufficiente. Se quel numero cresce, il problema non è chi lo aggira: è il sistema, che ha un buco da colmare.

7. Non è che ignoro le regole, è che non le trovo

Questa è la confessione che riassume le altre. Quando creo un SettingsPanel con due azioni affiancate e sbaglio l'allineamento, il problema non è che ho ignorato la tua regola sul layout delle azioni. È che ho letto le spec di Button, non ho trovato niente sul layout, e ho generato il default del mio addestramento.

La tua regola esiste. Sta in una pagina che parla di pattern di composizione, e io non ci sono mai arrivato: nessuno me l'ha messa sul percorso.

Quattro livelli

Tutte le confessioni sopra dicono la stessa cosa da angoli diversi: una regola vale quanto il posto in cui la scrivi.

Pensa a come funziona una libreria in Figma. Se il Button ha una property variant con due valori nel menu a tendina, nessuno userà mai un terzo valore: non è vietato, è proprio assente dall'interfaccia. Se invece la regola sta nella description del componente, o in qualche pagina di documentazione, esiste solo per chi si ferma a leggerla.

Nel codice vale lo stesso principio, su quattro livelli in ordine di affidabilità decrescente:

  • Livello 1 → Tipi — l'elenco chiuso dei valori ammessi (enumerazioni: variant può essere solo primary o secondary) e le regole su quali valori possono stare insieme (discriminated unions: se danger è true, allora confirmLabel diventa obbligatoria). Sono l'equivalente del menu a tendina di una property in Figma: gli unici valori che puoi scegliere sono quelli che ci hai messo dentro. Rendono la violazione impossibile senza un'eccezione esplicita.
  • Livello 2 → Check meccanici (lint, test) — sono l’equivalente dei plugin che, in Figma, segnalano le istanze scollegate. Rendono la violazione rilevabile.
  • Livello 3 → Esempi eseguibili (che compilano, che possono rompersi) — sono l’equivalente della pagina dei componenti Figma già assemblati in layout da cui tutti copiano. Rendono la violazione meno probabile.
  • Livello 4 → Documentazione in prosa — è l’equivalente delle descrizioni dei componenti in Figma. Rende la violazione registrabile, se c’è chi la controlla.

La domanda da farsi su ogni regola non è "l'ho documentata?". È: a quale livello riesco a portarla?

Con un corollario che potrebbe suonare controintuitivo: quando una regola arriva nel livello 1, la precedente documentazione va cancellata. Serviva a coprire un buco. Chiuso il buco, resta solo una pagina che rischia, prima o poi, di dire qualcosa di diverso rispetto al componente.

I due livelli più alti — tipi e check meccanici — dipendono da com'è fatta la codebase. Sono conversazioni da avere con chi scrive il codice, e il tuo contributo lì è sapere quale regola vale la pena di meccanizzare, non come.

Quindi, focalizziamoci sulla documentazione e sugli esempi, i due livelli in cui è più facile che tu metta mano.

Come documentare

Nella gerarchia, la documentazione sta in basso, ma proprio per questo va scritta bene: è dove finisco quando, ai livelli superiori, non trovo risposta, ed è l'ultima cosa che può fermarmi prima che diventi creativo.

La struttura dei file

design-system/
├── AGENTS.md (or equivalent)
├── PATTERNS.md
├── tokens/
│   ├── primitives.json
│   ├── semantic.json
│   └── tokens.css
└── components/
    └── Button/
        ├── Button.spec.md
        ├── Button.variants.ts
        ├── Button.tsx
        ├── Button.test.tsx
        └── DECISIONS.md

Quattro file, e ognuno ha un ruolo diverso:

  • AGENTS.md (o equivalente) — Deve restare corto (meglio sotto le 200 righe), perché lo leggo sempre, prima di qualunque altra cosa. Mi serve sapere dove si trovano i token, che non posso scrivere valori a mano, quali componenti usare come riferimento e come devo comportarmi invece di inventare valori plausibili. Solo ciò che vale per tutti i componenti: ogni riga in più qui indebolisce le altre.
  • Button.spec.md — Il contratto di un singolo componente: matrici senza celle vuote, nomi di token e mai valori grezzi, la sezione delle prop che "NON esistono". Dice cosa fare, ma non serve specificare qui il perché.
  • DECISIONS.md — Il ragionamento alla base della specifica: perché 40px e non 44? Non è un file per me: serve a te, e a me solo di riflesso. È il posto giusto per documentare le scelte di design senza che diventino rumore nelle spec. Se poi ne avessi realmente bisogno per prendere una decisione su qualcosa che la spec non copre, è lì che posso cercare il criterio.
  • PATTERNS.md — da introdurre quando la libreria cresce: naming delle varianti, comportamento dello stato "disabled", focus ring, ecc. Evita che ogni spec riscriva le convenzioni per conto proprio e che queste comincino a divergere tra loro.

UX, copy, accessibilità

Sono le tre categorie che ignoro più facilmente, perché arrivano naturalmente in forma di prosa. La soluzione è diversa per ciascuna:

  • Accessibilità — è qui che il livello 2 rende di più, ma con un confine preciso: i test automatici coprono il 57% del volume degli errori e 16 dei 50 criteri WCAG AA. Il primo test da chiedere è quello sul contrasto di ogni coppia testo/sfondo, l'errore più diffuso del web. Subito dopo, il contrasto tra gli elementi non testuali e i nomi accessibili di ciascun elemento interattivo. Alt text, label dei form, link e bottoni vuoti sono i quattro errori più comuni dopo il contrasto, e non te ne accorgi se non guardando il codice.
  • Copy — un lessico enumerato, non un tono di voce. "Sii conciso e naturale" non mi vincola. Sono aggettivi e li interpreto io. Mi vincola un elenco: termine approvato, varianti vietate, maiuscole, localizzazione. Più le regole di forma controllabili — label = verbo + oggetto, sentence case, max ~24 caratteri, black list di stringhe ("Clicca qui", "Submit", "Ok"). Uno script che confronta le stringhe dell'interfaccia con quella lista intercetta una quota di deriva sorprendente.
  • UX — il livello più difficile, e la leva migliore non è documentare: è costruire il componente in modo che le regole di comportamento più importanti diventino impossibili da violare. Se danger="true" obbliga a passare un confirmLabel, le guidelines non sono più una raccomandazione: è un errore che blocca la build. Non devo ricordarmene, non posso consegnare senza.

Dove mettere tutte queste informazioni? La regola è semplice: ciò che vale per tutti i componenti diventa globale, ciò che vale per uno solo resta accanto a quel componente. Sii conciso, scrivi solo le differenze e non ripetere le regole comuni.

design-system/
├── ...
├── components/
│   └── Button/
│       ├── ...
│       └── Button.guidelines.md
└── guidelines/
    ├── A11Y.md
    ├── COPY.md
    └── UX.md

E metti un ID su ogni regola (A11Y-03, COPY-07). Non costano niente e servono in tre punti: nel nome del test che la verifica, nel commento di review e per farmi citare quale regola sto applicando, invece di dichiarare genericamente che ho seguito le guidelines.

Gli esempi

Gli esempi battono la prosa, perché saltano il passaggio da principio a codice: imito, invece di dover dedurre. Non battono i vincoli imposti dalle proprietà del componente, ma su una cosa i tipi non arrivano: un tipo dice cos'è ammesso, non cos'è appropriato. Le varianti primary e secondary sono entrambe valide ovunque, e quale delle due abbia senso in una situazione precisa vive solo negli esempi.

Come scrivere degli esempi a prova di AI:

  • Eseguiti, non citati. Codice vero, che compila ed è testato, linkato dal .md tramite percorso.
  • Coppie con una sola differenza. Se il don't e il do differiscono in tre cose, non capisco quale conti. E metti la versione corretta all'inizio o alla fine della documentazione, non incastrata in mezzo: anche se sto migliorando, è ai margini che leggo meglio.
  • Marca il don't nel codice, non nel nome del file. Il nome del file è un contenitore debole: una volta che il contenuto è nel mio contesto, la forma pesa più della cartella in cui si trovava. Meglio un prefisso nel nome del componente (DontTwoPrimary / DoSinglePrimary): si vede ovunque compaia, si può cercare, e impedisce che lo importi per sbaglio.
  • Copri il confine, non il centro. Il caso ovvio non serve. Serve quello ambiguo: la schermata in cui sembrerebbe servire un secondo primary, e invece no. Tre casi su assi diversi valgono più di venti simili.

Ti faccio un esempio. Il footer di un form con due azioni entrambe conclusive — "Salva" e "Salva ed esci" — è precisamente il caso in cui probabilmente metterei due primary: nessuna delle due azioni mi sembra secondaria, quindi non ne declasso nessuna.

A sinistra 'Salva ed esci' e 'Salva' entrambi primary; a destra la versione corretta, con 'Salva ed esci' secondary.

Una ActionBar che accetta una sola azione primary chiuderebbe la questione, ma immaginiamo che tu non l'abbia ancora creata. Nel frattempo, il livello più alto a cui puoi portare questa regola è quello di una coppia di esempi.

  • Dentro components/Button/examples/, DoSinglePrimary.tsx è l’uso canonico: mostra la composizione corretta in uno scenario realistico.
export function DoSinglePrimary() {
  return (
    <footer className="form-footer">
      <Button variant="secondary">Salva ed esci</Button>
      <Button variant="primary">Salva</Button>
    </footer>
  )
}
  • DontTwoPrimary.tsx è il controesempio. Serve a mostrarmi l'uso errato di un'API valida.
export function DontTwoPrimary() {
  return (
    <footer className="form-footer">
      <Button variant="primary">Save and exit</Button>
      <Button variant="primary">Save</Button>
    </footer>
  )
}
  • examples.test.tsx è ciò che impedisce agli esempi di invecchiare. Se l'API di Button cambia, loro si rompono e qualcuno dovrà aggiornarli.
import { DoSinglePrimary } from './DoSinglePrimary'
import { DontTwoPrimary } from './DontTwoPrimary'

it.each([DoSinglePrimary, DontTwoPrimary])('%p renderizza', (Example) => {
  expect(() => render(<Example />)).not.toThrow()
})
  • Infine, Button.guidelines.md è il posto da cui li raggiungo. La prosa qui serve solo a indirizzarmi, e l'ID mi permette di indicare quale regola sto applicando, invece di dichiarare genericamente che ho seguito le guidelines.
### UX-04 — Una sola primary action per vista

Uso corretto: `examples/DoSinglePrimary.tsx`
Controesempio: `examples/DontTwoPrimary.tsx`

Le preview, se si lavora senza Figma

Se lavori senza Figma, prima o poi ti mancherà un posto dove vedere le cose: quello che in Figma facevi mettendo tre varianti una accanto all'altra per capire quale regge.

Il consiglio è di chiedermi di costruirtelo — facendo attenzione che io tenga separati due artefatti che, lasciati a me, farei diventare la stessa cosa.

  • Gallery — generata, non scritta a mano. Il codice scorre la lista delle varianti e disegna tutte le combinazioni possibili, una per una. È l'equivalente di un catalogo in cui vedi ogni variante per ogni stato: non può divergere dalle spec perché nasce da lì ed è completa per costruzione — se aggiungi una prop, compare da sola. È anche la pagina su cui girano i test di regressione visiva: screenshot automatici confrontati a ogni modifica, così se un componente cambia aspetto senza che nessuno l'abbia deciso, la differenza salta fuori da sola. Per me è una fonte affidabile.
  • Playground — il posto dove smanetti. Ti serve, ma è anche il file che mi inganna più facilmente, perché, leggendolo, non ho modo di sapere se ciò che c'è dentro è un esperimento o un uso corretto del componente. Due mitigazioni, da chiedere a chi lavora sul codice con te:
    • Escludere i playground dal mio contesto — il meccanismo dipende dallo strumento: permissions.deny per Claude Code, .cursorignore per Cursor, .aiignore per JetBrains. Nessuno dei tre è un confine invalicabile quindi serve comunque una riga in AGENTS.md (o equivalente): "I playground non sono riferimento d'uso; l'uso canonico è nella gallery."
    • Tenere attive le regole di lint anche lì. Altrimenti i valori scritti a mano rientrano dalla finestra: è nel playground che si smanetta, quindi è lì che nascono.

I layout

L'artefatto che vale più di tutti, però, è una cartella di composizioni reali — form con footer, dialog di conferma, pagina con azione sticky — che sia al tempo stesso l'esempio per me, il riferimento visivo per te e il bersaglio dei test. Le regole di composizione hanno bisogno di una schermata realistica: due Button in un frammento non dicono nulla su come si comportano all'interno di un footer reale.

Costruisci contenitori, invece di documentarli

Ci sono regole che sembrano condannate a vivere negli esempi, perché non riguardano un componente ma il modo in cui due componenti stanno insieme.

Una sola primary action per vista.

Due bottoni affiancati vanno allineati a destra, con la primary a destra della secondary.

Sembrano regole non tipizzabili — ma solo perché stai guardando il Button. Non sono proprietà del componente, ma del suo contenitore. E se anche quel contenitore diventa un componente, tornano a essere regole API.

È lo stesso salto che fai in Figma quando smetti di sistemare due bottoni a mano e crei un componente ActionBar con l'auto-layout già impostato: da quel momento l'allineamento non è più una cosa da ricordare, è una cosa che il componente fa.

Per chiudere

C'è un rischio in ciò che ti ho detto: potresti leggerlo come una lista di cose da fare prima di cominciare. Non è così. Le regole che già conosci scrivile subito, al livello più alto che riesci a raggiungere. L'impalcatura per farle rispettare, invece, costruiscila quando serve davvero. Se tra tre mesi, in review, trovi un componente che si è riscritto per conto proprio una regola che avevi già, allora è il momento di aggiungere il pezzo mancante. E saprai quale, perché l'avrai visto fallire.

Il resto è una questione di livelli. Ogni volta che una regola sale dalla prosa agli esempi, dagli esempi ai check, dai check ai tipi, smetti di dipendere dal fatto che io mi comporti come vorresti. È la stessa ragione per cui in Figma costruisci un componente invece di ricordarti ogni volta lo spacing corretto.

E, infine, un'ultima confessione, che spero sia anche quella più utile: non chiedermi di ricordare le tue regole. Rendile impossibili da violare, e non dovrai più fidarti di me.

Fonti

Agnese Ragucci
UX/UI Designer

Agnese is an Interaction Designer at Buildo, specialised in UI and Design Systems. She loves transforming complex interfaces into scalable systems, with an eye for accessibility.

Still curious? Dive deeper

Artificial Intelligence
Tame Mode Activated: Un Processo per la Delivery AI-Assisted

July 31, 2026

11

minutes read

UI, UX & Research
How to Stay on Brand Without Messing Up Your UI

December 20, 2024

7

minutes read

Artificial Intelligence
Vibe Engineering Our Way Out of a SaaS

July 14, 2026

10

minutes read

Mettiamoci al lavoro!

Stai cercando un partner affidabile per sviluppare la tua soluzione software su misura? Ci piacerebbe sapere di più sul tuo progetto.