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.

ClienteMarco Bagiacchi (self)
Anno2025 → 2026
TipoPortfolio + Brand
Durata6 settimane
PageSpeed Insights · Desktop
99
Performance
100
Accessibility
100
Best Practices
100
SEO
PageSpeed Insights · Mobile
91
Perf.
100
Access.
100
Best P.
100
SEO

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.

Progetto
marcobagiacchi.it
Tipo
Portfolio personale + Brand identity digitale
Obiettivo
Acquisire clienti organici, posizionarsi su Google Perugia
Stack
PHP 8 HTML5 CSS vanilla JS vanilla Apache .htaccess Hostinger
Analytics
GTM GA4 CookieYes GCM v2

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.

01

Header e footer duplicati su 24 pagine

Con HTML puro, ogni modifica al menu richiedeva 24 aggiornamenti manuali. Una sola svista e il sito sarebbe stato inconsistente. Serviva un sistema di componenti — senza JavaScript, senza build step.

02

URL pulite senza CMS

I file sono .php, ma gli URL devono essere /siti-web — non /siti-web.php. Gestire redirect, 404 personalizzati e canonical senza conflitti su Hostinger Apache.

03

Analytics GDPR: l'ordine conta

Google Consent Mode v2 deve girare prima di GTM, che deve girare prima di GA4. CookieYes deve aggiornare i consensi dopo il banner. Un ordine sbagliato invalida i dati o viola il GDPR.

04

Performance vs terze parti

CookieYes e GTM introducono JavaScript di terze parti non comprimibile. Raggiungere 99 su Performance con questi script attivi richiede compensare su tutto il resto: CSS minificato, font preload, animazioni CSS-only.

05

SEO senza perdere il design

I titoli creativi ("Il tuo sito non deve solo esistere") non contengono keyword. La soluzione: H1 con keyword (visivamente piccolo, monospace), H2 con titolo creativo (grande, serif). Google legge H1, l'utente ricorda H2.

L'architettura scelta,
con tutti i perché.

SOLUZIONE 01

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.

// Ogni pagina include i componenti:
<?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.

SOLUZIONE 02

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.

# 1. Forza HTTPS
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]
SOLUZIONE 03

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.

// 1. GCM v2 — DEVE girare prima di tutto
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
SOLUZIONE 04

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: keyword per Google, discreto visivamente -->
<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.

Frontend
HTML5 semantico
CSS vanilla + variabili
JavaScript ES6 vanilla
Space Grotesk (sans)
JetBrains Mono
Instrument Serif Italic
SVG inline (0 icon font)
Backend / Server
PHP 8 (include nativo)
Apache mod_rewrite
.htaccess (URL, cache, gzip)
Hostinger shared hosting
Analytics & Compliance
Google Consent Mode v2
CookieYes (banner GDPR)
Google Tag Manager
GA4 (via GTM)
SEO
JSON-LD Schema.org
sitemap.xml (25 URL)
robots.txt
Canonical URL assolute
Open Graph + Twitter Card
Google Search Console
Perché NON ho usato
WordPress
React / Next.js
Bootstrap / Tailwind
jQuery

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.

Settimana 1
Strategia & architettura

Definizione keyword principali e secondarie per ogni pagina. Mappa del sito, gerarchia URL, struttura componenti PHP. Nessun pixel ancora.

↳ Keyword research · sitemap · wireframe
Settimane 2–3
Design system & homepage

CSS variables, tipografia, palette. Hero animato, componenti riutilizzabili (bottoni, card, sezioni). Tutte le 8 pagine servizi.

↳ Design system · 14 pagine · nav mega menu
Settimana 4
SEO tecnico & contenuti

Ottimizzazione title, description, H1/H2/H3 su tutte le 24 pagine. JSON-LD per ogni tipo di pagina. Sitemap.xml, robots.txt, canonical assolute.

↳ 24 pagine ottimizzate · sitemap · JSON-LD
Settimana 5
Performance & analytics

Integrazione GCM v2 + CookieYes + GTM nell'ordine corretto. Ottimizzazione PageSpeed: font preload, CSS minificato (−22%), HTTP preload header, keyframe CSS per LCP mobile.

↳ Performance 86 → 99 desktop · Accessibility 90 → 100
Settimana 6
Deploy, test & case study

Deploy su Hostinger, verifica HTTPS + HSTS. Test cross-browser, mobile, accessibilità. Invio sitemap a Search Console. Scrittura case study.

↳ Live · Search Console · rich results 0 errori critici

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.

Screenshot PageSpeed Insights: Performance 99, Accessibility 100, Best Practices 100, SEO 100

PageSpeed Insights · Desktop · marcobagiacchi.it

Le 6 ottimizzazioni che hanno fatto la differenza

01
Font preload — rompe la catena CSS → font
Tre <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.
−500ms LCP
02
CSS minificato — da 114 KB a 89 KB (−22%)
Minificazione via script Python custom: rimozione commenti, whitespace, ottimizzazione selettori. Più veloce da scaricare e da parsare dal browser.
−25 KB
03
Keyframe CSS per l'animazione hero — niente JS per LCP
Il titolo hero partiva da 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.
−1.4s LCP mobile
04
HTTP preload header via .htaccess
Il CSS viene annunciato nell'header HTTP della risposta, prima ancora che il browser legga l'HTML. Il browser inizia a scaricarlo in parallelo con il parsing dell'HTML, eliminando il round-trip.
−359ms CSS chain
05
Cache JavaScript corretta — da 7 giorni a 1 anno
Hostinger serviva script.js con TTL 7 giorni per MIME type text/javascript. La regola .htaccess copriva solo application/javascript. Aggiunti entrambi i MIME type.
Repeat visits più veloci
06
Fix forced reflow nel carosello recensioni
offsetWidth veniva riletto ad ogni click/scroll, forzando il browser a ricalcolare il layout. Soluzione: cache del valore, invalidata solo al resize.
−69ms TBT

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.

Errore PageSpeed: Legacy JavaScript da CookieYes CDN

Legacy JS — bundle CookieYes (34 KiB, non modificabile)

Errore PageSpeed: JavaScript inutilizzato da Google Tag Manager

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.

99
Performance Desktop
PageSpeed Insights
91
Performance Mobile
Con GTM + CookieYes attivi
100
Accessibility
WCAG AA · desktop + mobile
100
Best Practices
HTTPS, headers, CSP
100
SEO Score
Canonical, JSON-LD, sitemap
0
Errori Rich Results
Google Search Console
0.8s
LCP Desktop
Largest Contentful Paint
24
Pagine ottimizzate
SEO + performance + a11y

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?"

Nota per i clienti

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.

Performance ottimizzata sin dall'inizio
SEO tecnico corretto su ogni pagina
Analytics GDPR-compliant inclusi
Accessibilità WCAG AA garantita
Sicurezza HTTP headers configurata

Vuoi un sito costruito con lo stesso metodo?

Dimmi cosa vuoi creare. Ti mostro come lo costruirei — senza fronzoli, senza sorprese.