Colophon / la sala macchine, aperta

L'architettura giusta è quella dimensionata sul problema.

Il problema qui è preciso: un archivio personale che deve essere veloce, costare zero, farsi leggere da umani, crawler e agenti, e lasciarsi mantenere in autopilot. Da lì discende tutto il resto di questa pagina.

Requisiti → decisioni

Leggero

HTML statico servito da CDN, client JS solo dove c'è interazione. Il collo di bottiglia dev'essere la lettura, mai il caricamento.

Zero overhead

Nessun server, nessun database, nessun CMS: niente da patchare, niente che si buca, niente che chiama alle 3 di notte. Un archivio personale non deve chiedere attenzione operativa.

Economico

Build statica su piano hobby: il costo marginale di una visita è ~zero, e il costo fisso pure. I soldi vanno nei contenuti, non nell'hosting.

Autopilot

Il sito si mantiene da solo: io dico cosa serve, code-os (si apre in una nuova scheda) lo costruisce, il gate decide se si spedisce. agent-memory (si apre in una nuova scheda) con le regole e la definition of done, decisioni registrate come ADR: una sessione agentica nuova è produttiva al primo prompt, senza di me a fare da memoria.

Findability / token

Anche l'architettura dei dati è per gli agenti: dati tipizzati in src/content con path prevedibili, un componente per responsabilità, nomi che dicono cosa fanno. Qualsiasi cosa si trova senza bruciare token in esplorazione: il contesto minimo sufficiente è una proprietà della repo, non del prompt.

SEO + GEO

Statico è crawlabile per definizione, e uso Next per quello che sa fare: Metadata API per canonical e OpenGraph, sitemap e robots tipizzati, OG image generate a build time con ImageResponse, font self-hosted via next/font (zero layout shift), JSON-LD nei layout. Per chi cerca via AI: llms.txt e /api/dossier, dalla stessa fonte delle pagine.

Non commerciale

Niente funnel, niente popup, niente tracker di terzi (analytics cookieless e basta). È un archivio da leggere, non una landing da convertire.

// anche questa pagina: ho detto cosa volevo, l'harness l'ha costruita, il gate l'ha approvata.

Architettura

Decision record

  1. ADR-001accepted12 LUG 2026

    Zero dipendenze, più una

    Runtime: Next + React + react-aria-components (accessibilità dei widget: focus management, press semantics, focus trap: cose che sbagli se le riscrivi). Niente Tailwind, CMS, UI kit, librerie di animazione. Conseguenza: superficie di update minima, ogni riga in bundle è giustificabile.

  2. ADR-002accepted12 LUG 2026

    Tutto statico, sempre

    Ogni route (HTML, OG image, llms.txt, /api/dossier) è generata a build time e servita da CDN. Nessun compute a runtime: niente cold start, superficie d'attacco ridotta al minimo, costo marginale per request ~zero. Il vincolo è accettato: contenuto nuovo = nuovo deploy.

  3. ADR-003accepted12 LUG 2026

    Il contenuto è un tipo, non una pagina

    Essay, principi, work vivono in src/content come oggetti tipizzati (SSoT). Archivio, homepage, sitemap, OG, llms.txt e /api/dossier derivano dalla stessa fonte. Conseguenza: un contenuto si scrive una volta e non può divergere tra i formati.

  4. ADR-004accepted12 LUG 2026

    Un solo accento

    #E35B2D, ovunque; sulla neve una sfumatura più scura (#B8481C) per il contrasto AA su testo piccolo: stessa tinta, non un secondo colore. Vale anche negli easter egg: una nevicata ha esattamente un fiocco arancione.

  5. ADR-005accepted12 LUG 2026

    Motion come decorazione, mai come gate

    Lo stato nascosto dello scroll-reveal esiste solo con JS attivo (@media scripting) e motion consentito. JS spento o prefers-reduced-motion: contenuto integro. Le animazioni sono un layer sopra il contenuto, non una precondizione per leggerlo.

  6. ADR-006accepted12 LUG 2026

    Accessibilità come invariante

    Skip-link con target focusabile, focus ring visibile, aria-current sulla navigazione, contrasti AA, link esterni annunciati, aria-live anche per gli easter egg. Trattata come i test: una regressione è un bug, non un compromesso.

  7. ADR-007accepted12 LUG 2026

    Leggibile dalle macchine

    /llms.txt per gli agenti, /api/dossier per curl, JSON-LD per i crawler: tutti generati dallo stesso SSoT delle pagine, quindi mai disallineati. Il contesto su di me lo servo io, nel formato di chi lo consuma.

  8. ADR-008accepted16 LUG 2026

    Tre lingue, un SSoT

    IT, EN, PL come route statiche (/it /en /pl), hreflang per pagina, slug condivisi. Niente middleware: la detection è un redirect statico. La parità tra lingue è verificata a build time: una traduzione mancante rompe la build, non la fiducia.

  9. ADR-009accepted28 OTT 2026

    Il mondo è il banner

    Il sito diventa SimoFree: il banner LinkedIn, vivo. Canvas disegnato una volta sola per dimensione (niente loop), tutto ciò che si legge o si preme è DOM sopra il canvas, nella stessa camera. Neve come base, inchiostro, un solo accento. L'easter egg è un gioco vero, opzionale.

  10. ADR-010accepted28 OTT 2026

    Due lettori: persone e agenti

    Ogni pagina ha un gemello Markdown generato dalla stessa fonte, più llms.txt, llms-full.txt e un server MCP in sola lettura. L'HTML resta canonico; il Markdown è noindex. Lo switch Umano / Agente mostra cosa legge un agente.

  11. ADR-011accepted28 OTT 2026

    Run e piste

    I casi sono run (slug condivisi, storie senza numeri del cliente); i modi di lavorare sono piste (slug per lingua, una frase cercata per pagina, difficoltà codificata per forma, mai solo per colore).

  12. ADR-012accepted30 OTT 2026

    Classifica di SimoFree verificata per replay

    Il server non si fida di un numero. Dà il seed, il browser registra gli input a passo fisso (120 Hz) e il server rigioca la discesa con la stessa simulazione pura per calcolare il punteggio. Ticket monouso, tempo reale minimo, limiti per IP salvati come HMAC, solo punteggi positivi, top 100 su Upstash.

  13. ADR-013accepted8 NOV 2026

    Un solo movimento continuo: il cielo nel footer

    La discesa finisce di notte: nel footer c'è un cielo a puntini (dither 1 bit) con lo yeti in orbita. Il canvas si disegna una volta per dimensione; lo yeti è un layer DOM spostato solo con transform, scritto solo quando la posa cambia di un pixel. Il loop gira solo se il cielo è a schermo e nessuno lo ha messo in pausa (WCAG 2.2.2). Con reduced motion lo yeti sta fermo e il loop non parte. È l'eccezione alla regola niente animazioni infinite; ADR-014 estende lo stesso contratto al resto del sito.

  14. ADR-014accepted8 NOV 2026

    Il mondo si muove: una regia, un interruttore

    La testata è il banner vivo: Simone scende, salta dalla cornice (un trick diverso a ogni giro, una caduta ogni quattro) e lo yeti lo insegue e perde. La coreografia è una funzione pura del tempo, testata, e si apre sul fotogramma esatto del banner. Il canvas resta fermo; si muovono solo layer DOM via transform. Ogni animazione ambientale passa da un solo hook (a schermo, mai in background) e da un solo interruttore di pausa per tutto il sito. Lo scroll è una discesa: nella nav una porta per sezione. Torino, Milano e Warszawa all'orizzonte.

  15. ADR-015accepted8 NOV 2026

    Anche la scrollbar è della pista

    Su mouse e trackpad la barra nativa diventa un binario sottile: il cursore è un box HUD nell'accento quando lo usi, ogni sezione numerata è una porta con il suo nome, da trascinare o cliccare. Lo scroll nativo resta intatto (tastiera, rotella, touch, tecnologie assistive), il binario lo rispecchia soltanto ed è aria-hidden. La barra nativa sparisce solo dopo che il binario è montato, quindi senza JS o su touch resta quella del sistema. Segue lo scroll, non è movimento ambientale: una variabile CSS per frame.

Per le macchine

Il contenuto su di me lo servo io, nel formato di chi lo consuma. Gli agenti leggono /llms.txt; chi preferisce il terminale ha un endpoint JSON generato dallo stesso SSoT delle pagine:

curl simonebova.com/api/dossier

// stessa fonte, tre formati: HTML per te, llms.txt per gli agenti, JSON per curl.