Case study — portfolio personale
Il sito che stai guardando,
spiegato dall'interno.
Ogni decisione tecnica, ogni ottimizzazione SEO, ogni scelta di architettura — documentata nel dettaglio. Non per vantarmi, ma perché questo è esattamente il metodo che uso su ogni progetto cliente.
Partire da zero,
consapevolmente.
Il vecchio sito girava su WordPress con un tema commerciale. Funzionava, ma pesava: ogni pagina caricava plugin inutilizzati, JS non necessario e CSS gonfiato da un builder che pensava per centinaia di layout diversi, non per il mio.
La decisione è stata netta: riscrivere tutto da zero in HTML/PHP vanilla, senza framework, senza CMS, senza compromessi. Un sito che pesa esattamente quanto deve pesare — non un byte in più.
Il vincolo principale: Hostinger shared hosting. Niente Node.js, niente build pipeline. Tutto doveva girare con PHP nativo e Apache — una costrizione che si è rivelata una virtù: zero dipendenze, massimo controllo.
Un sito portfolio non deve impressionare chi lo fa. Deve impressionare chi lo vede — e farlo in meno di 3 secondi.
Cosa doveva fare
il sito.
Prima di toccare il codice, ho definito ogni requisito. Un sito portfolio per un freelance non è solo una vetrina — è uno strumento di conversione che lavora 24h su 24.
Velocità di caricamento percepita ≤ 1 s
First Contentful Paint sotto 1 secondo su connessioni standard. Il visitatore deve vedere contenuto prima di decidere se restare.
Posizionamento organico su "sviluppatore web Perugia"
Keyword principale con intento commerciale. Il SEO tecnico deve essere perfetto: struttura H1/H2, JSON-LD, sitemap, canonical.
PageSpeed 100 su Accessibility, Best Practices, SEO
Nessun compromesso sull'accessibilità: contrasti WCAG AA, ARIA corretti, semantica HTML pulita.
Analytics GDPR-compliant con Consent Mode v2
Google Consent Mode v2 attivo prima di qualsiasi script. CookieYes gestisce il banner. GA4 via GTM — zero double-tracking.
Design memorabile, non generico
Dark theme con accenti cyan/purple. Typography mista serif/mono. Hero animato, elementi interattivi. Un sito che si ricorda.
Sicurezza e header HTTP corretti
HSTS, X-Frame-Options, CSP base, blocco directory listing, protezione file sensibili (.env, .git). Tutto via .htaccess.
I problemi da risolvere
prima di scrivere una riga.
Ogni progetto ha i suoi nodi da sciogliere. Questo ne aveva cinque, e ognuno aveva implicazioni sull'architettura dell'intera soluzione.
L'architettura scelta,
con tutti i perché.
Sistema a componenti PHP
Invece di un framework o un CMS, ho usato il PHP include nativo.
Tre file condivisi — header.php,
footer.php,
analytics.php —
inclusi in ogni pagina via $_SERVER['DOCUMENT_ROOT'].
Risultato: modifico il menu in un posto solo, il cambio si propaga a tutte le 24 pagine. Zero JavaScript richiesto lato server, zero dipendenze esterne, compatibile al 100% con Hostinger.
<?php include $_SERVER['DOCUMENT_ROOT']
. '/components/header.php'; ?>
// header.php contiene nav, mobile menu,
// GTM noscript — un solo file da aggiornare
<?php include $_SERVER['DOCUMENT_ROOT']
. '/components/footer.php'; ?>
Perché non JS fetch? Un componente caricato via fetch non è visibile ai crawler SEO al momento del crawl iniziale — rischio indicizzazione.
Clean URL via .htaccess
Quattro regole Apache in sequenza risolvono tutti i casi: forza HTTPS,
rimuove www, toglie l'estensione .php dagli URL,
gestisce il caso speciale di /progetti/
(directory reale + file PHP con lo stesso nome — senza la regola dedicata dà redirect infinito).
Il 301 canonico su ogni URL garantisce che Google indicizzi sempre e solo la versione corretta:
https://marcobagiacchi.it/siti-web, mai con .php o www.
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# 2. Rimuovi .php dall'URL
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,L]
# 3. Fix speciale /progetti/ → /progetti
RewriteRule ^progetti/$ /progetti [R=301,L]
RewriteRule ^progetti$ progetti.php [L]
# 4. Serve .php per URL pulite
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.php [L]
Stack Analytics GDPR-compliant
L'ordine di caricamento non è negoziabile. Un file PHP condiviso —
analytics.php —
incluso in ogni <head> garantisce sempre la sequenza corretta.
CookieYes caricato con async:
rimuove il blocco al rendering (−900ms), ma il
wait_for_update: 2000
nel GCM v2 garantisce che GTM aspetti i consensi prima di sparare eventi.
gtag("consent", "default", {
analytics_storage: "denied",
wait_for_update: 2000, // aspetta CookieYes
});
// 2. CookieYes — async, non blocca il render
<script id="cookieyes" async
src="cdn-cookieyes.com/..."></script>
// 3. GTM — carica GA4, attende i consensi
// GA4 NON viene incluso direttamente:
// evita il double-tracking
Gerarchia H1/H2 per SEO e design
I titoli creativi non contengono keyword — ma sono memorabili. Le keyword non sono memorabili — ma Google le ama. La soluzione: usarli entrambi, insieme.
H1 = keyword in stile eyebrow (monospace, 12px, uppercase) — visibile ma discreto.
H2 = titolo creativo (display serif, grande) — quello che l'utente ricorda.
H3 = titoli di sezione con keyword secondarie.
Nessun testo nascosto, nessuna tecnica gray-hat. Google legge H1 e sale nel ranking, l'utente legge H2 e decide di restare.
<h1 style="font-family:var(--mono);
font-size:12px;text-transform:uppercase">
Sviluppatore web Perugia
</h1>
<!-- H2: titolo creativo per l'utente -->
<h2 class="h-display">
Il tuo sito <u>non</u> deve
solo esistere.
Deve farsi <em>ricordare.</em>
</h2>
Risultato: SEO 100/100 su PageSpeed, struttura validata da Google Search Console.
Ogni strumento scelto
con un motivo preciso.
La regola è semplice: nessuna dipendenza senza un vantaggio misurabile. Ogni libreria aggiunta è un rischio di sicurezza, un peso sulle performance, una versione da aggiornare. Per un sito statico come questo, vanilla è la scelta più professionale.
Come ho lavorato,
settimana per settimana.
6 settimane di sviluppo non-lineare: design e codice sono andati avanti in parallelo, con cicli iterativi brevi. Nessuna spec documento di 40 pagine — solo decisioni veloci, test continui e refactoring immediato.
Definizione keyword principali e secondarie per ogni pagina. Mappa del sito, gerarchia URL, struttura componenti PHP. Nessun pixel ancora.
CSS variables, tipografia, palette. Hero animato, componenti riutilizzabili (bottoni, card, sezioni). Tutte le 8 pagine servizi.
Ottimizzazione title, description, H1/H2/H3 su tutte le 24 pagine. JSON-LD per ogni tipo di pagina. Sitemap.xml, robots.txt, canonical assolute.
Integrazione GCM v2 + CookieYes + GTM nell'ordine corretto. Ottimizzazione PageSpeed: font preload, CSS minificato (−22%), HTTP preload header, keyframe CSS per LCP mobile.
Deploy su Hostinger, verifica HTTPS + HSTS. Test cross-browser, mobile, accessibilità. Invio sitemap a Search Console. Scrittura case study.
Da 86 a 99 su Desktop.
Ogni punto, guadagnato.
La performance non è un numero da mostrare — è il tempo che i tuoi visitatori non perdono ad aspettare. Ogni ottimizzazione ha richiesto analisi, test e a volte il coraggio di fare passi indietro quando la soluzione scelta peggiorava le cose.
PageSpeed Insights · Desktop · marcobagiacchi.it
Le 6 ottimizzazioni che hanno fatto la differenza
<link rel="preload" as="font"> in <head> fanno partire il download dei woff2 in parallelo con il CSS, eliminando la dipendenza CSS→font dalla catena critica.opacity:0 e aspettava l'IntersectionObserver JS. Su mobile con 4× CPU throttle, questo ritardava il LCP di 800–1500ms. Soluzione: @keyframes CSS puri, nessuna dipendenza da JS.text/javascript. La regola .htaccess copriva solo application/javascript. Aggiunti entrambi i MIME type.offsetWidth veniva riletto ad ogni click/scroll, forzando il browser a ricalcolare il layout. Soluzione: cache del valore, invalidata solo al resize.Perché la Performance mobile è 91 e non 100
I 9 punti mancanti su mobile non dipendono dal sito — dipendono da CookieYes e Google Tag Manager, script di terze parti obbligatori per GDPR e analytics. Non sono modificabili: appartengono a server esterni, con codice legacy e bundle fissi.
Legacy JS — bundle CookieYes (34 KiB, non modificabile)
Unused JS — GTM bundle (61 KiB, non modificabile)
Questi stessi errori appaiono su qualsiasi sito che usa GTM + un CMP (Consent Management Platform). Non sono un problema del sito — sono il costo necessario per analytics GDPR-compliant. Il 99/100 realisticamente raggiungibile su mobile con questi script è già stato ottenuto su desktop.
I numeri finali,
senza filtri.
Cosa ho imparato
costruendo questo sito.
Vanilla batte qualsiasi framework per siti statici. Nessuna dipendenza da aggiornare, nessun bundle da ottimizzare, nessuna astrazione da imparare. Il CSS finale è 89 KB — un'app React "Hello World" pesa di più.
Il CSS preload trick senza critical CSS inline è una trappola. La prima implementazione ha fatto crollare la performance da 86 a 56. Il FOUC (flash of unstyled content) peggiora LCP e CLS più di quanto il preload li migliori.
Le animazioni JS bloccano il LCP su mobile. IntersectionObserver su CPU throttle 4× ritarda il reveal dell'elemento hero di 800–1500ms. Soluzione: keyframe CSS puri che partono appena il browser ha parsato il foglio di stile.
L'ordine degli script analytics non è documentato chiaramente da Google. GCM v2 → CookieYes async → GTM. Invertire anche un solo passaggio invalida i dati o viola GDPR. Il wait_for_update: 2000 è il collante che tiene insieme tutto.
Il contrasto non è un optional estetico. Cambiare --ink-3 in --ink-2 su quattro elementi ha portato Accessibility da 90 a 96. Aggiungere i cache buster ha fatto il resto.
Un sito ben costruito è il miglior portfolio possibile. Non serve mostrare cosa sai fare — basta mostrarlo. Ogni cliente che arriva su questo sito vede già la risposta alla domanda "come lavori?"
Questo è il metodo che uso su ogni progetto
L'architettura che vedi qui — componenti PHP, SEO tecnico strutturato, analytics GDPR-compliant, performance ottimizzata — non è riservata al mio sito. È il punto di partenza per ogni progetto che seguo.
Cosa cambia tra progetto e progetto? Il contenuto, il design, le integrazioni specifiche. La qualità tecnica di base resta la stessa.
Vuoi un sito costruito con lo stesso metodo?
Dimmi cosa vuoi creare. Ti mostro come lo costruirei — senza fronzoli, senza sorprese.