Caso de estudio — portfolio personal
La web que estás viendo,
explicada desde dentro.
Cada decisión técnica, cada optimización SEO, cada elección de arquitectura, documentadas al detalle. No para presumir, sino porque este es exactamente el método que uso en cada proyecto de cliente.
Empezar de cero,
a conciencia.
La web anterior funcionaba con WordPress y un tema comercial. Funcionaba, pero pesaba: cada página cargaba plugins sin usar, JS innecesario y CSS inflado por un constructor pensado para cientos de layouts distintos, no para el mío.
La decisión fue tajante: reescribirlo todo desde cero en HTML/PHP vanilla, sin framework, sin CMS, sin concesiones. Una web que pesa exactamente lo que tiene que pesar, ni un byte más.
La restricción principal: hosting compartido de Hostinger. Nada de Node.js, nada de pipeline de build. Todo tenía que funcionar con PHP nativo y Apache, una limitación que resultó ser una virtud: cero dependencias, máximo control.
Una web portfolio no tiene que impresionar a quien la hace. Tiene que impresionar a quien la ve, y hacerlo en menos de 3 segundos.
Lo que tenía que hacer
la web.
Antes de tocar el código, definí cada requisito. La web portfolio de un freelance no es solo un escaparate: es una herramienta de conversión que trabaja las 24 horas.
Velocidad de carga percibida ≤ 1 s
First Contentful Paint por debajo de 1 segundo con conexiones normales. El visitante tiene que ver contenido antes de decidir si se queda.
Posicionamiento orgánico para "sviluppatore web Perugia" (desarrollador web Perugia)
La keyword principal, con intención comercial. El SEO técnico tiene que ser perfecto: estructura H1/H2, JSON-LD, sitemap, canonical.
PageSpeed 100 en Accesibilidad, Buenas prácticas y SEO
Ninguna concesión en accesibilidad: contrastes WCAG AA, ARIA correctos, HTML semántico limpio.
Analítica conforme al RGPD con Consent Mode v2
Google Consent Mode v2 activo antes de cualquier script. CookieYes gestiona el banner. GA4 vía GTM: cero doble medición.
Un diseño memorable, no genérico
Tema oscuro con acentos cian y morado. Tipografía mixta serif/mono. Hero animado, elementos interactivos. Una web que se recuerda.
Seguridad y cabeceras HTTP correctas
HSTS, X-Frame-Options, CSP básica, listado de directorios bloqueado, archivos sensibles protegidos (.env, .git). Todo vía .htaccess.
Los problemas que resolver
antes de escribir una línea.
Cada proyecto tiene sus propios nudos que deshacer. Este tenía cinco, y cada uno afectaba a la arquitectura de toda la solución.
La arquitectura elegida,
con todos sus porqués.
Sistema de componentes en PHP
En lugar de un framework o un CMS, usé el include nativo de PHP. Tres archivos compartidos (header.php, footer.php, analytics.php) incluidos en cada página mediante $_SERVER['DOCUMENT_ROOT'].
Resultado: modifico el menú en un solo sitio y el cambio se propaga a las 24 páginas. Cero JavaScript necesario, cero dependencias externas, 100% compatible con Hostinger.
<?php include $_SERVER['DOCUMENT_ROOT']
. '/components/header.php'; ?>
// header.php contiene nav, menú móvil,
// GTM noscript: un solo archivo que actualizar
<?php include $_SERVER['DOCUMENT_ROOT']
. '/components/footer.php'; ?>
¿Por qué no un fetch en JS? Un componente cargado con fetch no es visible para los rastreadores en el rastreo inicial: riesgo para la indexación.
URLs limpias con .htaccess
Cuatro reglas de Apache en secuencia resuelven todos los casos: fuerzan HTTPS, quitan el www, eliminan la extensión .php de las URLs y gestionan el caso especial de /progetti/ (un directorio real + un archivo PHP con el mismo nombre: sin la regla específica, provoca una redirección infinita).
El 301 canónico en cada URL garantiza que Google indexe siempre y solo la versión correcta: https://marcobagiacchi.it/siti-web, nunca con .php ni con www.
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# 2. Quitar .php de la URL
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,L]
# 3. Corrección especial /progetti/ → /progetti
RewriteRule ^progetti/$ /progetti [R=301,L]
RewriteRule ^progetti$ progetti.php [L]
# 4. Servir .php para URLs limpias
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.php [L]
Stack de analítica conforme al RGPD
El orden de carga no es negociable. Un archivo PHP compartido (analytics.php) incluido en cada <head> garantiza siempre la secuencia correcta.
CookieYes se carga con async: elimina el bloqueo del renderizado (−900 ms), y el wait_for_update: 2000 de GCM v2 garantiza que GTM espere los consentimientos antes de lanzar eventos.
gtag("consent", "default", {
analytics_storage: "denied",
wait_for_update: 2000, // espera a CookieYes
});
// 2. CookieYes — async, no bloquea el renderizado
<script id="cookieyes" async
src="cdn-cookieyes.com/..."></script>
// 3. GTM — carga GA4, espera los consentimientos
// GA4 NO se incluye directamente:
// evita la doble medición
Jerarquía H1/H2 para el SEO y el diseño
Los títulos creativos no contienen keywords, pero se recuerdan. Las keywords no se recuerdan, pero a Google le encantan. La solución: usar ambos, juntos.
H1 = keyword con estilo de antetítulo (monoespaciada, 12 px, mayúsculas): visible pero discreta.
H2 = título creativo (serif display, grande): el que recuerda el usuario.
H3 = títulos de sección con keywords secundarias.
Ningún texto oculto, ninguna técnica gris. Google lee el H1 y sube en el ranking; el usuario lee el H2 y decide quedarse.
<h1 style="font-family:var(--mono);
font-size:12px;text-transform:uppercase">
Desarrollador web Perugia
</h1>
<!-- H2: título creativo para el usuario -->
<h2 class="h-display">
Tu web <u>no</u> solo tiene
que existir.
Tiene que <em>recordarse.</em>
</h2>
Resultado: SEO 100/100 en PageSpeed, estructura validada por Google Search Console.
Cada herramienta elegida
por un motivo preciso.
La regla es sencilla: ninguna dependencia sin una ventaja medible. Cada librería añadida es un riesgo de seguridad, un lastre para el rendimiento y una versión más que actualizar. Para una web estática como esta, vanilla es la opción más profesional.
Cómo trabajé,
semana a semana.
6 semanas de desarrollo no lineal: diseño y código avanzaron en paralelo, en ciclos iterativos cortos. Ningún documento de especificaciones de 40 páginas: solo decisiones rápidas, pruebas continuas y refactorización inmediata.
Definición de las keywords principales y secundarias de cada página. Mapa del sitio, jerarquía de URLs, estructura de componentes PHP. Todavía ni un píxel.
Variables CSS, tipografía, paleta. Hero animado, componentes reutilizables (botones, tarjetas, secciones). Las 8 páginas de servicios.
Optimización de title, description y H1/H2/H3 en las 24 páginas. JSON-LD para cada tipo de página. Sitemap.xml, robots.txt, canonical absolutas.
Integración de GCM v2 + CookieYes + GTM en el orden correcto. Optimización de PageSpeed: precarga de fuentes, CSS minificado (−22%), cabecera HTTP de precarga, keyframes CSS para el LCP en móvil.
Despliegue en Hostinger, comprobación de HTTPS + HSTS. Pruebas en varios navegadores, móvil y accesibilidad. Envío del sitemap a Search Console. Redacción del caso de estudio.
De 86 a 99 en escritorio.
Cada punto, ganado.
El rendimiento no es un número para presumir: es el tiempo que tus visitantes no pierden esperando. Cada optimización exigió análisis, pruebas y, a veces, el valor de dar marcha atrás cuando la solución elegida empeoraba las cosas.
PageSpeed Insights · Escritorio · marcobagiacchi.it
Las 6 optimizaciones que marcaron la diferencia
<link rel="preload" as="font"> en el <head> inician la descarga de los woff2 en paralelo con el CSS, eliminando la dependencia CSS→fuente de la cadena crítica.opacity:0 y esperaba al IntersectionObserver de JS. En móvil con la CPU ralentizada 4×, esto retrasaba el LCP entre 800 y 1500 ms. Solución: @keyframes en CSS puro, sin dependencia de JS.text/javascript. La regla del .htaccess solo cubría application/javascript. Se añadieron ambos tipos MIME.offsetWidth se volvía a leer en cada clic/scroll, obligando al navegador a recalcular el layout. Solución: guardar el valor en caché e invalidarlo solo al redimensionar.Por qué el rendimiento en móvil es 91 y no 100
Los 9 puntos que faltan en móvil no dependen de la web: dependen de CookieYes y Google Tag Manager, scripts de terceros obligatorios para el RGPD y la analítica. No se pueden modificar: están en servidores externos, con código antiguo y paquetes fijos.
JS antiguo — paquete de CookieYes (34 KiB, no modificable)
JS sin usar — paquete de GTM (61 KiB, no modificable)
Estos mismos errores aparecen en cualquier web que use GTM + una CMP (plataforma de gestión del consentimiento). No son un problema de la web: son el coste necesario de una analítica conforme al RGPD. El 99/100 alcanzable de forma realista con estos scripts ya se ha conseguido en escritorio.
Los números finales,
sin filtros.
Lo que aprendí
construyendo esta web.
Vanilla gana a cualquier framework en webs estáticas. Ninguna dependencia que actualizar, ningún paquete que optimizar, ninguna abstracción que aprender. El CSS final pesa 89 KB: una app "Hello World" en React pesa más.
El truco de precargar el CSS sin CSS crítico inline es una trampa. La primera implementación hundió el rendimiento de 86 a 56. El FOUC (destello de contenido sin estilo) empeora el LCP y el CLS más de lo que la precarga los mejora.
Las animaciones en JS bloquean el LCP en móvil. IntersectionObserver con la CPU ralentizada 4× retrasa la aparición del elemento del hero entre 800 y 1500 ms. Solución: keyframes en CSS puro que arrancan en cuanto el navegador ha procesado la hoja de estilos.
Google no documenta con claridad el orden de los scripts de analítica. GCM v2 → CookieYes async → GTM. Invertir un solo paso invalida los datos o incumple el RGPD. El wait_for_update: 2000 es el pegamento que lo mantiene todo unido.
El contraste no es un extra estético. Cambiar --ink-3 por --ink-2 en cuatro elementos llevó la Accesibilidad de 90 a 96. Añadir los cache busters hizo el resto.
Una web bien construida es el mejor portfolio posible. No hace falta contar lo que sabes hacer: basta con demostrarlo. Cada cliente que llega a esta web ya ve la respuesta a la pregunta "¿cómo trabajas?".
Este es el método que uso en cada proyecto
La arquitectura que ves aquí (componentes PHP, SEO técnico estructurado, analítica conforme al RGPD, rendimiento optimizado) no está reservada a mi web. Es el punto de partida de cada proyecto que llevo.
¿Qué cambia de un proyecto a otro? El contenido, el diseño, las integraciones concretas. La calidad técnica de base sigue siendo la misma.
¿Quieres una web construida con el mismo método?
Cuéntame qué quieres crear. Te enseño cómo lo construiría: sin adornos, sin sorpresas.