Vai al contenuto
Tutti i lavori
  • #web
  • #design-system
  • #webgl
  • #i18n

leafranger.dev

Questo sito: un portfolio in due lingue in Next.js 16 con un design system tutto suo, un campo di particelle che disegna il mio drago come una mesh low-poly, e accessibilità e SEO verificate dai test a ogni modifica.

Sito web
Ruolo
Unico designer e sviluppatore: il design system, il codice e i testi in entrambe le lingue.
Risultato
Lighthouse 100 su accessibilità, best practice e SEO da mobile, senza spostamenti di layout. Ogni pagina in entrambe le lingue viene verificata in CI: stato, tag SEO, dati strutturati, axe in entrambi i temi, larghezza da telefono.
Anno
2026
Stato
in corso
Stack
  • Next.js 16
  • React 19
  • TypeScript
  • Tailwind 4
  • three.js
  • React Three Fiber
  • Radix
  • MDX
  • Playwright
  • Vercel
  1. L'inizio

    Una prima versione che faceva il suo lavoro

    La prima versione di questo sito è andata online a giugno 2025, con una pagina per i miei lavori su Roblox e una per i progetti personali. Faceva il suo lavoro, ma volevo di più: un sito che raccontasse com'è andato ogni progetto invece di elencarlo e basta, e che sembrasse mio.

  2. L'obiettivo

    Un solo sito per tre tipi di visitatori

    Clienti che cercano un bot o un'automazione, studi Roblox che cercano suoni, interfacce o script, e aziende che valutano il mio lavoro: tutti devono trovare quello che cercano e un modo chiaro per scrivermi. In italiano e in inglese, con la stessa sostanza. E doveva sembrare mio, con il mio drago e i miei colori, non un template.

  3. L'avventura

    Ricostruito da zero

    L'ho ricostruito un pezzo alla volta. Prima un linguaggio visivo con regole sue: il viola per tutto ciò che si può premere, il lime per ciò che è attivo, angoli quasi squadrati, e ogni pulsante, menu e player progettato una volta e riusato ovunque. Poi ogni pagina in due lingue, i case study da leggere per schede, e le pagine Roblox dove ogni suono si ascolta e ogni interfaccia si apre.

    La pagina Roblox, pensata per gli studi: il mio nome come un muro di mattoncini da sfiorare e far esplodere.

    La parte di cui vado più fiero è il drago in home. È fatto di particelle che lasciano lo sfondo e si radunano nel mio avatar, poi si girano a seguire il puntatore. Clicca sullo sfondo e si scompone al rallentatore, per poi ricomporsi.

  4. La fine

    Un sito che si controlla da solo

    Si carica in fretta, funziona da tastiera e con uno screen reader, e resta tranquillo per chi preferisce meno movimento. Ogni volta che cambio qualcosa, ogni pagina in entrambe le lingue viene verificata automaticamente prima di andare online. È ancora in corso: il redesign arriva pagina per pagina, e questo case study cresce con lui.

Lighthouse accessibilità, best practice e SEO
100
Lighthouse accessibilità, best practice e SEO
Lingue, stessa sostanza
2
Lingue, stessa sostanza
Spostamenti di layout durante il caricamento
0
Spostamenti di layout durante il caricamento

Prossimi passi

  • Ancora più veloce

    Su un telefono gli effetti richiedono un po' di caricamento prima della prima schermata. Caricarne una parte più tardi è il prossimo passo.

  • Più media miei

    Screenshot e clip reali per ogni progetto, e i miei modelli 3D.

  • Un design system tutto suo

    Ruoli dei colori (viola per premere, lime per ciò che è attivo), token tipografici fluidi, tre raggi per gli angoli e un kit di pulsanti, form, menu, media e dialoghi, tutti in una pagina laboratorio.

  • Un drago fatto di particelle

    La home disegna il mio avatar come una mesh low-poly che si gira verso il puntatore; un clic lo fa esplodere e poi lo ricompone.

  • Due lingue, un solo sito

    Ogni pagina in italiano e in inglese. Cambiare lingua non ferma la pagina: il nuovo testo entra dietro una linea di scansione lime.

  • Accessibile in partenza

    Titoli e testo veri dietro ogni effetto, un contorno di focus visibile, il link per saltare al contenuto, il contrasto verificato in entrambi i temi e una versione ferma per il movimento ridotto.

  • Funziona anche senza effetti

    La scrivania 3D nella pagina Chi sono ha accanto un elenco di pulsanti, quindi funziona da tastiera e senza WebGL, dove l'elenco è tutto.

  • Consenso fatto bene

    Niente di Google si carica prima di una scelta. Rifiuta e Accetta hanno la stessa dimensione, e Impostazioni cookie nel footer permette di cambiare idea in ogni momento.

  • Leggibile da motori di ricerca e AI

    Tag canonical e hreflang, immagini di condivisione generate in fase di build, una sola Person nei dati strutturati di ogni pagina e file llms.txt generati dai dati dei progetti.

  • Verificato a ogni modifica

    La CI esegue lint, il controllo dei tipi, una build di produzione e i test su ogni pagina della sitemap.

Due temi

Il tema scuro è quello predefinito e il chiaro è a un clic, svelato da un cerchio che si allarga dal pulsante. Il tema chiaro non è lo scuro al contrario: i pannelli si sollevano su un'ombra leggera, i bordi dei campi sono più scuri per restare visibili e il testo lime passa a una tonalità più profonda, perché quella brillante è troppo chiara da leggere sul bianco.

Roblox, disciplina per disciplina

Ogni disciplina ha la sua pagina, con il suo spazio di lavoro come sfondo e ogni gioco come un pannello di suoni, immagini, video o script.

La pagina Roblox porta a una pagina per disciplina. Ogni gioco si apre come un pannello, raggruppato come è stato fatto il lavoro, con un player per ogni suono e un lightbox per ogni immagine. Un link può puntare dritto a un gioco o a un gruppo, e un pulsante per commissionare un lavoro compare appena il titolo esce dallo schermo.

Lavori da filtrare

Gli argomenti in comune tra almeno due progetti diventano filtri. La scelta resta nell'indirizzo, così un link come «Guarda questi lavori» della home apre l'elenco già filtrato.

Su un telefono

Sui telefoni il drago ha una fascia tutta sua sotto l'header e il testo inizia sotto, così niente lo copre. I pulsanti diventano a tutta larghezza, la navigazione diventa un menu a schermo intero, e il cambio lingua lo chiude così la linea di scansione passa sulla pagina.

Quando una pagina non esiste

Gli indirizzi sconosciuti restano dentro il sito: le particelle disegnano il 404, e le due uscite sono a un clic.

Lo stack

  • Framework

    Next.js 16, React 19

    App Router con Turbopack, server component di default e il proxy di Next 16 per il reindirizzamento della lingua. Pubblicato su Vercel, con route API per le parti che richiedono una chiave segreta lato server.

  • Stile

    Tailwind 4

    Configurazione in CSS: i token di colori, tipografia, angoli ed easing sono variabili CSS in un unico foglio del design system, cambiate dalla classe del tema.

  • 3D

    three.js, React Three Fiber

    L'hero a voxel della pagina Roblox e la scrivania della pagina Chi sono, caricati solo quando servono, messi in pausa fuori dallo schermo e sostituiti da un poster senza WebGL2.

  • Contenuti

    MDX

    Case study e pagine dei giochi sono MDX per lingua, con blocchi come il percorso, le statistiche e le sfide usabili senza import.

Il campo di particelle

Dietro la pagina ci sono due canvas: lo strato principale con il plexus e la forma dell'hero, e uno strato lontano con tre livelli di profondità sfocati.

  1. Campionamento

    Un Web Worker legge i pixel dell'avatar e li divide in punti di contorno, occhiali, denti, bocca, lingua e riempimento.
  2. Mesh

    I punti vengono triangolati con Delaunator; restano solo i triangoli sull'inchiostro con lati corti.
  3. Reclutamento

    Mentre l'hero è sullo schermo, le particelle dello sfondo lasciano la loro posizione e si posano sui punti della forma.
  4. Ombreggiatura

    Le facce vengono raggruppate per colore e illuminate da un riflesso che gira con il drago verso il puntatore.

Ogni particella dello sfondo ha una posizione di riposo presa da una sequenza a bassa discrepanza, quindi qualunque prefisso della lista è distribuito in modo uniforme: reclutare dalla fine lascia uniforme il resto del campo. I livelli di profondità si muovono con una parallasse 1/z, e la loro sfocatura è disegnata con sprite gaussiani invece che con filtri CSS.

Le lingue

Ogni pagina vive sotto /en o /it. Un indirizzo senza lingua riceve un 307 verso la lingua salvata in un cookie, altrimenti verso quella del browser che corrisponde meglio, altrimenti verso l'inglese. I testi dell'interfaccia stanno in due dizionari, e quello italiano è tipizzato su quello inglese, quindi una chiave mancante fa fallire il controllo dei tipi. I testi lunghi sono MDX per lingua.

Sopra le lingue c'è un solo layout radice, quindi cambiare lingua è una navigazione leggera: campo di particelle, cursore e suono continuano a girare, e una view transition con nome accoppia la pagina vecchia e quella nuova sotto la linea di scansione.

Sfide

Problema

Un thread principale bloccato

Campionare il drago richiedeva circa 850 ms su un telefono di fascia media, un blocco nel mezzo della prima visita.

Soluzione

Il campionamento è passato in un Web Worker. Il suo avvio vive fuori dal modulo delle forme, perché un URL del worker dentro il modulo che il worker stesso importa mandava in loop la build di Turbopack.

Problema

Una sfocatura che costava fotogrammi

Tre canvas sfocati via CSS giravano a 3-4 fps in rendering software.

Soluzione

La sfocatura viene disegnata: i punti sono sprite gaussiani e i collegamenti un tratto largo e tenue sotto uno sottile, su un canvas a risoluzione 0,6.

Problema

Un banner dei cookie in ritardo

Disegnato dopo l'idratazione, il banner diventava l'elemento più grande e più lento di ogni prima visita.

Soluzione

Arriva già nell'HTML del server, nascosto dal CSS finché uno script inline, eseguito prima del primo disegno, non segna la pagina come in attesa di una scelta.

Problema

Un hydration mismatch

Con il proxy davanti, il percorso poteva essere diverso tra l'HTML del server e l'idratazione, e l'indicatore della pagina corrente nell'header non coincideva.

Soluzione

L'header ora legge la route dai segmenti del layout renderizzato, che fanno parte dell'albero, quindi server e client sono sempre d'accordo.

Controlli di qualità

  • Test di base

    Playwright

    Ogni pagina della sitemap: stato, un solo h1, canonical, hreflang, immagine di condivisione, dati strutturati con la Person, nessun errore in console, niente scorrimento laterale alla larghezza di un telefono.

  • Accessibilità

    axe

    Le pagine principali in entrambi i temi, senza violazioni gravi o critiche, più il flusso del consenso, il 404 localizzato e il movimento ridotto.

  • Sicurezza

    Header

    Una content security policy e gli altri header di sicurezza su ogni route, e route API che validano l'input e servono solo ciò che è in una lista consentita.

  • CI

    GitHub Actions

    Lint, controllo dei tipi, una build di produzione e i test a ogni push.

Il codice sorgente è pubblico?

No, il repository è privato. Posso mostrarne volentieri qualsiasi parte in una chiamata.

Mi traccia?

Solo se accetti gli analytics. Fino ad allora non si carica niente di Google, e l'informativa privacy elenca ogni servizio con cui parla il tuo browser.

Perché il plexus c'è solo in home?

È la firma del sito, ma dietro i testi da leggere era troppo. Tutte le altre pagine hanno uno sfondo pieno.

Cosa succede senza WebGL o con il movimento ridotto?

Le scene 3D lasciano il posto a un poster o a un elenco di pulsanti, e con il movimento ridotto le particelle restano ferme, le forme si compongono subito e l'intro viene saltata.

Puoi costruire qualcosa del genere per me?

Sì. Dimmi cosa deve fare e per quando ti serve, nella pagina contatti.

Ti serve qualcosa di simile?

Dimmi cosa deve fare, dove gira e per quando ti serve.

Contattami