🔍 Auditoría Exhaustiva del Portfolio — 72 Hallazgos
Fecha: 2026-03-22
Tech Stack: Next.js 15.5.9, React 19, TypeScript, Tailwind CSS 3.4, Framer Motion
Resumen Ejecutivo
| Categoría |
🔴 Crítico |
🟠 Alto |
🟡 Medio |
🔵 Bajo |
Total |
| A. Visual/UX |
1 |
3 |
5 |
3 |
12 |
| B. Rendimiento |
0 |
4 |
5 |
3 |
12 |
| C. SEO |
1 |
3 |
4 |
2 |
10 |
| D. Accesibilidad |
1 |
4 |
4 |
2 |
11 |
| E. Seguridad |
1 |
2 |
3 |
2 |
8 |
| F. Calidad de Código |
1 |
3 |
4 |
3 |
11 |
| G. Mejores Prácticas |
1 |
2 |
3 |
2 |
8 |
| TOTAL |
6 |
21 |
28 |
17 |
72 |
🔴 Problemas Críticos (6)
A.1 — favicon.ico está vacío (0 bytes)
- Archivo:
public/favicon.ico
- El archivo favicon.ico tiene 0 bytes. Navegadores sin soporte SVG no mostrarán icono.
- Fix: Generar favicon.ico real a partir del favicon.svg (16x16, 32x32, 48x48).
C.1 — URLs externas en sitemap.xml
- Archivo:
public/sitemap.xml:95-116
- El sitemap incluye URLs de dominios externos (imdb.com, filmaffinity.com, wikipedia.org). Google puede penalizar el sitemap completo.
- Fix: Eliminar todas las URLs externas del sitemap.
D.1 — Sin link "Skip to content"
- Archivo:
src/app/layout.tsx, src/app/page.tsx
- No existe enlace "Saltar al contenido principal". WCAG 2.4.1 (Bypass Blocks) - Nivel A.
- Fix: Añadir
<a href="#main-content">Saltar al contenido</a> y id="main-content" al <main>.
E.1 — API de contacto sin validación Zod ni rate limiting
- Archivo:
src/app/api/contact/route.ts:10-29
- Validación manual básica en lugar del schema Zod existente. Sin rate limiting, permite abuso (spam, DoS).
- Fix: Usar
contactFormSchema.parse(body) y añadir rate limiting.
F.1 — Directorio anidado erróneo: src/lib/src/lib/
- Archivo:
src/lib/src/lib/analytics.ts
- Directorio duplicado creado por error de copia.
- Fix: Eliminar
src/lib/src/ completo.
G.1 — Faltan assets PWA referenciados en manifests
- Archivos:
public/manifest.json, public/site.webmanifest
- Múltiples archivos referenciados que no existen: android-chrome-192x192.png, android-chrome-512x512.png, apple-touch-icon.png, screenshots/, og-image.jpg, twitter-image.jpg, profile-image.jpg, etc.
- Fix: Generar todos los assets referenciados o actualizar las referencias.
🟠 Problemas de Alta Importancia (21)
A. Visual/UX (3)
A.2 — Menú móvil sin AnimatePresence funcional
- Archivo:
src/components/Navbar.tsx:108-177
- Animaciones de salida nunca se ejecutan. Menú desaparece abruptamente.
- Fix: Envolver en
<AnimatePresence>.
A.3 — Scroll no bloqueado al abrir menú móvil
- Archivo:
src/components/Navbar.tsx
- Usuario puede hacer scroll en el fondo con el menú abierto.
- Fix:
document.body.style.overflow = 'hidden' al abrir.
A.4 — 12 links de navegación sin scroll visible en desktop
- Archivo:
src/components/Navbar.tsx:9-22
- En pantallas 1024-1280px, los 12 enlaces probablemente no caben.
- Fix: Implementar submenú dropdown o reducir ítems visibles.
B. Rendimiento (4)
B.1 — Imágenes servidas desde GitHub user-attachments
- GitHub no es CDN optimizado. Sin redimensionado dinámico, caché impredecible.
- Fix: Migrar a CDN dedicado (Vercel Blob, Cloudinary).
B.2 — 29 componentes de secciones, 9 sin usar (~110KB código muerto)
Collaborators.tsx, Events.tsx, FAQ.tsx, FeaturedRoles.tsx, News.tsx, Portfolio.tsx, SkillsGraph.tsx, SkillsVisual.tsx, Stats.tsx
- Fix: Eliminar componentes no utilizados.
B.3 — Framer Motion importado en prácticamente todos los componentes
- ~140KB minificado usado para animaciones simples que podrían ser CSS.
- Fix: Usar CSS para animaciones simples, Framer Motion solo para complejas.
B.4 — Skills sin Suspense wrapper
dynamic() sin <Suspense> → sin fallback visual mientras carga.
- Fix: Envolver en
<Suspense fallback={<SectionSkeleton />}>.
C. SEO (3)
C.2 — Anchor links (#) en sitemap.xml
- Motores de búsqueda ignoran fragmentos hash. Entradas inútiles.
- Fix: Eliminar URLs con fragmentos.
C.3 — Conflicto entre robots.txt estático y robots.ts dinámico
- Archivo estático tiene prioridad y bloquea *.json$ y *.xml$.
- Fix: Eliminar
public/robots.txt, usar solo src/app/robots.ts.
C.4 — Google verification placeholder no real
- Valores placeholder
'pending-verification'. Google Search Console no verificado.
- Fix: Completar verificación con código real o eliminar placeholder.
D. Accesibilidad (4)
D.2 — Navbar links sin aria-current para lectores de pantalla
- Sección activa solo indicada visualmente. WCAG 4.1.2.
- Fix: Añadir
aria-current={isActive ? 'true' : undefined}.
D.3 — Botón menú móvil sin aria-expanded
- Sin
aria-expanded ni aria-controls. WCAG 4.1.2.
- Fix: Añadir atributos ARIA al botón hamburguesa.
D.4 — Select de contacto sin contraste adecuado
- Opciones del dropdown con problemas de contraste sobre
bg-neutral-900. WCAG 1.4.3.
D.5 — Social links sin aria-label descriptivos
- Solo muestran icono sin indicar que son enlaces externos. WCAG 2.4.4.
- Fix: Añadir
aria-label descriptivos.
E. Seguridad (2)
E.2 — CSP permite unsafe-eval y unsafe-inline
- Archivo:
next.config.js:95
- Anula protección CSP contra XSS.
- Fix: Eliminar
'unsafe-eval', usar nonces.
E.3 — Formspree endpoint hardcoded y expuesto
- Archivo:
src/components/sections/Contact.tsx:25
- Cualquiera puede enviar formularios directamente.
- Fix: Proxiar a través de API route con rate limiting.
F. Calidad de Código (3)
F.2 — Dos archivos Prettier config
.prettierrc y .prettierrc.json en la raíz.
- Fix: Eliminar uno.
F.3 — Dos archivos Lighthouse config
lighthouserc.js y lighthouserc.json.
- Fix: Mantener solo uno.
F.4 — Contact.tsx no usa Zod de validators.ts
- Validación HTML nativa en lugar de Zod + react-hook-form (ambos instalados).
- Fix: Integrar react-hook-form con @hookform/resolvers/zod.
G. Mejores Prácticas (2)
G.2 — No hay página 404 personalizada
- Next.js muestra 404 genérica. No coincide con el diseño del sitio.
- Fix: Crear
src/app/not-found.tsx.
G.3 — Dos manifests PWA
manifest.json y site.webmanifest con contenido diferente.
- Fix: Mantener solo uno.
🟡 Problemas de Prioridad Media (28)
Ver todos los problemas medios
| # |
Categoría |
Descripción |
Archivo |
| A.5 |
Visual |
Partículas con posición absoluta basada en window size |
Contact.tsx |
| A.6 |
Visual |
Hero extremadamente largo en móvil |
Hero.tsx |
| A.7 |
Visual |
Texto "Professional Headshots" mezclando idiomas |
Hero.tsx:444 |
| A.8 |
Visual |
Fan counter en Footer con localStorage sin backend |
Footer.tsx |
| A.9 |
Visual |
Doble Footer component (uno no usado) |
layouts/Footer.tsx |
| B.5 |
Rendimiento |
Service Worker sin versionado de cache |
sw.js |
| B.6 |
Rendimiento |
Múltiples implementaciones de Analytics |
analytics.ts (x3) |
| B.7 |
Rendimiento |
21+ archivos markdown en raíz del proyecto |
./ |
| B.8 |
Rendimiento |
Preconnect a dominios no utilizados |
layout.tsx |
| B.9 |
Rendimiento |
Prefetch de anchor links sin efecto |
layout.tsx |
| C.5 |
SEO |
og-image.jpg y twitter-image.jpg no existen |
layout.tsx |
| C.6 |
SEO |
Metadatos duplicados layout.tsx vs metadata.ts |
metadata.ts |
| C.7 |
SEO |
hreflang apunta a /en inexistente |
layout.tsx |
| C.8 |
SEO |
SearchAction en schema sin búsqueda real |
layout.tsx |
| D.6 |
Accesibilidad |
Mínimo uso de aria-labels (17 en 52 archivos) |
Múltiples |
| D.7 |
Accesibilidad |
Animaciones sin prefers-reduced-motion |
Múltiples |
| D.8 |
Accesibilidad |
Menú móvil sin focus trap |
Navbar.tsx |
| D.9 |
Accesibilidad |
Heading hierarchy inconsistente |
Múltiples |
| E.4 |
Seguridad |
Google Analytics ID placeholder |
Analytics.tsx |
| E.5 |
Seguridad |
Sentry tracesSampleRate al 100% |
sentry.client.config.ts |
| E.6 |
Seguridad |
Email expuesto en múltiples ubicaciones |
Múltiples |
| F.5 |
Código |
Componentes layouts/ no usados |
layouts/ |
| F.6 |
Código |
Constants.ts NAVIGATION_ITEMS no coincide con Navbar |
constants.ts |
| F.7 |
Código |
trackEvent con dos firmas incompatibles |
analytics.ts |
| F.8 |
Código |
suppressHydrationWarning en html y body |
layout.tsx |
| G.4 |
Prácticas |
No hay package-lock.json |
./ |
| G.5 |
Prácticas |
Falta error.tsx para errores de runtime |
src/app/ |
| G.6 |
Prácticas |
No hay estilos de impresión (@media print) |
globals.css |
🔵 Problemas de Baja Prioridad (17)
Ver todos los problemas bajos
| # |
Categoría |
Descripción |
Archivo |
| A.10 |
Visual |
styled-jsx repetido múltiples veces en Hero |
Hero.tsx |
| A.11 |
Visual |
Color de acento inconsistente manifest vs theme-color |
manifest.json, layout.tsx |
| A.12 |
Visual |
About con loading="eager" innecesario below-the-fold |
About.tsx |
| B.10 |
Rendimiento |
critical.css no se usa ni se inyecta |
critical.css |
| B.11 |
Rendimiento |
console.log en Service Worker producción |
sw.js |
| B.12 |
Rendimiento |
Bundle analyzer importado incondicionalmente |
next.config.js |
| C.9 |
SEO |
Sitemap estático en lugar de dinámico |
sitemap.xml |
| C.10 |
SEO |
Schema.org image apunta a archivo inexistente |
layout.tsx |
| D.10 |
Accesibilidad |
Color contrast text-slate-400 sobre fondos oscuros |
Múltiples |
| D.11 |
Accesibilidad |
Imágenes decorativas sin aria-hidden |
Múltiples |
| E.7 |
Seguridad |
Fecha de nacimiento expuesta en schema |
layout.tsx |
| E.8 |
Seguridad |
security.txt sin GPG key |
security.txt |
| F.9 |
Código |
index como key en varios componentes |
Múltiples |
| F.10 |
Código |
react-hook-form y resolvers instalados sin usar |
package.json |
| F.11 |
Código |
Variable --font-serif sin fuente Playfair cargada |
globals.css |
| G.7 |
Prácticas |
IMAGES_TODO.md servido públicamente |
public/ |
| G.8 |
Prácticas |
Falta loading.tsx para transiciones |
src/app/ |
Plan de Corrección
La rama feature/audit-fixes abordará todos los problemas en el siguiente orden:
- 🔴 Críticos — Fixes inmediatos
- 🟠 Altos — Mejoras prioritarias
- 🟡 Medios — Refinamiento
- 🔵 Bajos — Pulido final
🔍 Auditoría Exhaustiva del Portfolio — 72 Hallazgos
Fecha: 2026-03-22
Tech Stack: Next.js 15.5.9, React 19, TypeScript, Tailwind CSS 3.4, Framer Motion
Resumen Ejecutivo
🔴 Problemas Críticos (6)
A.1 — favicon.ico está vacío (0 bytes)
public/favicon.icoC.1 — URLs externas en sitemap.xml
public/sitemap.xml:95-116D.1 — Sin link "Skip to content"
src/app/layout.tsx,src/app/page.tsx<a href="#main-content">Saltar al contenido</a>yid="main-content"al<main>.E.1 — API de contacto sin validación Zod ni rate limiting
src/app/api/contact/route.ts:10-29contactFormSchema.parse(body)y añadir rate limiting.F.1 — Directorio anidado erróneo: src/lib/src/lib/
src/lib/src/lib/analytics.tssrc/lib/src/completo.G.1 — Faltan assets PWA referenciados en manifests
public/manifest.json,public/site.webmanifest🟠 Problemas de Alta Importancia (21)
A. Visual/UX (3)
A.2 — Menú móvil sin AnimatePresence funcional
src/components/Navbar.tsx:108-177<AnimatePresence>.A.3 — Scroll no bloqueado al abrir menú móvil
src/components/Navbar.tsxdocument.body.style.overflow = 'hidden'al abrir.A.4 — 12 links de navegación sin scroll visible en desktop
src/components/Navbar.tsx:9-22B. Rendimiento (4)
B.1 — Imágenes servidas desde GitHub user-attachments
B.2 — 29 componentes de secciones, 9 sin usar (~110KB código muerto)
Collaborators.tsx,Events.tsx,FAQ.tsx,FeaturedRoles.tsx,News.tsx,Portfolio.tsx,SkillsGraph.tsx,SkillsVisual.tsx,Stats.tsxB.3 — Framer Motion importado en prácticamente todos los componentes
B.4 — Skills sin Suspense wrapper
dynamic()sin<Suspense>→ sin fallback visual mientras carga.<Suspense fallback={<SectionSkeleton />}>.C. SEO (3)
C.2 — Anchor links (#) en sitemap.xml
C.3 — Conflicto entre robots.txt estático y robots.ts dinámico
public/robots.txt, usar solosrc/app/robots.ts.C.4 — Google verification placeholder no real
'pending-verification'. Google Search Console no verificado.D. Accesibilidad (4)
D.2 — Navbar links sin aria-current para lectores de pantalla
aria-current={isActive ? 'true' : undefined}.D.3 — Botón menú móvil sin aria-expanded
aria-expandedniaria-controls. WCAG 4.1.2.D.4 — Select de contacto sin contraste adecuado
bg-neutral-900. WCAG 1.4.3.D.5 — Social links sin aria-label descriptivos
aria-labeldescriptivos.E. Seguridad (2)
E.2 — CSP permite unsafe-eval y unsafe-inline
next.config.js:95'unsafe-eval', usar nonces.E.3 — Formspree endpoint hardcoded y expuesto
src/components/sections/Contact.tsx:25F. Calidad de Código (3)
F.2 — Dos archivos Prettier config
.prettierrcy.prettierrc.jsonen la raíz.F.3 — Dos archivos Lighthouse config
lighthouserc.jsylighthouserc.json.F.4 — Contact.tsx no usa Zod de validators.ts
G. Mejores Prácticas (2)
G.2 — No hay página 404 personalizada
src/app/not-found.tsx.G.3 — Dos manifests PWA
manifest.jsonysite.webmanifestcon contenido diferente.🟡 Problemas de Prioridad Media (28)
Ver todos los problemas medios
🔵 Problemas de Baja Prioridad (17)
Ver todos los problemas bajos
Plan de Corrección
La rama
feature/audit-fixesabordará todos los problemas en el siguiente orden: