Logo
Volver
Repositorio del Portafolio Personal en GitHub

Portafolio Personal

Open Source

Portafolio full-stack construido con Next.js, DDD y Arquitectura Limpia en un monorepo Turborepo.

  • TypeScript
  • React
  • Next.js
  • Node.js
  • PostgreSQL
  • Tailwind CSS
  • CI/CD
  • Prisma
  • Supabase

Tras seis años en ingeniería de software, este portafolio fue la primera oportunidad de ser dueño de un producto completo — desde la arquitectura hasta el deploy. Construido para ir más allá de LinkedIn hacia una audiencia internacional, para buscar oportunidades en el exterior y para demostrar que Domain-Driven Design y Arquitectura Limpia se sostienen en un proyecto solo desde cero — no solo en equipos donde el proceso es impuesto.

Las Restricciones

La arquitectura fue autoimpuesta. Sin equipo, sin plazo y sin presión externa, la restricción vino de una decisión deliberada: tratar el proyecto como un producto real con un alcance de MVP, un roadmap post-MVP y sin atajos en la capa de dominio.

Tres requisitos moldearon cada decisión técnica:

  • Performance — el sitio tenía que puntuar bien en Lighthouse; un portafolio lento envía el mensaje equivocado
  • Contenido sin cambiar código — actualizar entradas de proyectos o experiencias no podía requerir un deploy; todo el contenido está impulsado por una base de datos con seed y renderizado como markdown
  • i18n en todas las capas — soportar inglés, portugués y español significaba resolver la internacionalización en la capa de dominio, no solo parchearlo en la UI

El diseño visual fue creado íntegramente en Figma por Milena Kawai, una amiga diseñadora que entregó la especificación completa desde cero.

Proceso de Ingeniería

El backlog fue gestionado con Task Master, dividido en sprints rastreados como milestones de GitHub. GitHub Projects proporcionó un tablero Kanban para el seguimiento; cada issue seguía un template estructurado con contexto, criterios de aceptación, archivos relevantes y dependencias. Labels personalizadas organizaron el trabajo por sprint, prioridad y tipo.

El proyecto se estructuró en cinco PRDs numerados — uno por capa de arquitectura:

  • Sprint 0 — fundación del dominio (core): patrón Either, Value Objects, entidades, interfaces de repositorio
  • Sprint 1 — capa de aplicación: use cases, ports, DTOs
  • Sprint 2 — infraestructura: repositorios Prisma, gateway Supabase, contenedor de DI
  • Sprint 3 — sitio público: Next.js App Router, SSG, enrutamiento i18n, componentes de UI
  • Sprint 4 — CI/CD: verificación de tipos, linting y suite de pruebas en GitHub Actions

Un sprint dedicado a accesibilidad resolvió 88 problemas de WCAG, seguido de un paso orientado por Lighthouse que apuntó al bundle crítico, hints de preload de RSC y carga de la imagen LCP.

La carpeta docs/ contiene 12 documentos de arquitectura numerados — contextos delimitados, estrategia de validación, enfoque de i18n, estrategia de pruebas, patrones de código y glosario de dominio.

Arquitectura

El dominio está organizado en tres contextos delimitados — portfolio (proyectos, experiencias, skills, perfil), identity (autenticación y usuario) y contact (envío de mensajes) — cada uno con sus propias entidades, value objects e interfaces de repositorio, compartiendo solo el Shared Kernel.

Cada paquete tiene una única responsabilidad aplicada mecánicamente:

  • core — modelo de dominio; cero dependencias de framework; entidades, value objects, patrón Either, interfaces de repositorio
  • application — use cases y ports; depende solo de core; sin Prisma, sin HTTP
  • infra — implementaciones concretas; única capa que importa Prisma y Supabase
  • ui — biblioteca de componentes React; dividida en View (visualización) y Control (interactividad)
  • utils — utilidades TypeScript puras: Validator, formateadores, hooks de browser; sin dependencia de React

Sitio del Portafolio

Los Server Components llaman a use cases directamente en el build time — no existe ninguna capa REST entre el dominio y el HTML generado. Para un sitio estático orientado a contenido, un límite HTTP sería overhead puro.

La internacionalización es una preocupación de dominio: LocalizedText es un value object en core. El sitio renderiza en inglés, portugués y español — resuelto en la capa de dominio antes de que cualquier componente React toque los datos.

Cada página exporta generateMetadata con campos title, description y openGraph localizados. Las páginas de proyectos derivan los datos de OG directamente de las entidades de dominio — título, caption e imagen de portada — asegurando que los metadatos nunca queden desincronizados con el contenido. Una ruta de imagen OG personalizada, construida con next/og en el Edge Runtime, genera cards 1200×630 con identidad visual por página, locale y proyecto.

Las rutas de detalle de proyecto están impulsadas por Slug — un value object en core — con generateStaticParams resolviendo cada slug de proyecto publicado en las tres locales en build time. Sin slug, sin ruta.

El formulario de contacto pasa por rate limiting via Upstash Redis y entrega correo electrónico a través de Resend — ambos detrás de interfaces de puerto, intercambiables y testeables sin tocar la infraestructura.

Este portafolio es la primera presencia técnica pública que construí y poseo completamente — desde el modelo de dominio hasta el pipeline de deploy. La app admin para gestión de contenido y el blog están previstos como post-MVP, manteniendo el sitio actual enfocado y publicable.

Aspectos Destacados

  • Sin capa de API — los Server Components consumen use cases en build time; un sitio estático no necesita un límite HTTP entre dominio y HTML
  • Dirección de dependencia aplicada por ESLint — las violaciones de capa se detectan en lint time, no en code review; el límite es mecánico, no una convención
  • Patrón Either — no se lanzan excepciones para errores de dominio; Left<ValidationError> se propaga por los use cases hasta la UI, haciendo todos los caminos de error explícitos y testeables
  • LocalizedText como VO — i18n es una preocupación de dominio; los componentes reciben strings ya resueltos, no claves de traducción
  • Accesibilidad como sprint — 88 problemas de WCAG rastreados, acotados y entregados como issues individuales con criterios de aceptación
  • Performance orientada por Lighthouse — bundle crítico reducido con lazy-loading de formularios pesados, eliminación de 'use client' innecesarios y preload de la imagen LCP con fetchpriority=high
  • SEO y Open Graph — cada página exporta generateMetadata localizado; una ruta /og en Edge Runtime genera cards 1200×630 por página, locale y proyecto usando next/og; los datos de OG se derivan de las entidades de dominio, nunca de strings estáticos

Tecnologías

  • Next.js — App Router con SSG; generateStaticParams genera todas las rutas localizadas en build time
  • Turborepo — orquestación de monorepo con cinco paquetes compartidos y caché remoto en Vercel
  • TypeScript — modo strict en todos los paquetes; any está prohibido
  • Prisma — ORM y capa de migraciones, aislado en packages/infra
  • Supabase — base de datos PostgreSQL y autenticación basada en JWT
  • Tailwind CSS — tokens de diseño compartidos via packages/tailwind-config
  • next-intl — enrutamiento de locale y resolución de mensajes para EN, PT-BR y ES
  • Vitest — pruebas unitarias e integración en todos los paquetes; ~100 archivos de prueba
  • Upstash Redis — rate limiting serverless en el formulario de contacto
  • Resend — correo electrónico transaccional para envíos del formulario de contacto
  • Vercel — deployment con caché remoto de Turborepo

Otros proyectos

  • Plataforma B2B TC Representações — tienda mayorista restringida para materiales de construcción

    Plataforma B2B de E-Commerce

    Plataforma B2B full-stack para materiales de construcción con Arquitectura Limpia, React y Node.js — de cero a producción.

    • TypeScript
    • React
    Ver proyecto