Logo
Voltar
Repositório do Portfólio Pessoal no GitHub

Portfólio Pessoal

Open Source

Portfólio full-stack construído com Next.js, DDD e Arquitetura Limpa em um monorepo Turborepo.

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

Após seis anos em engenharia de software, este portfólio foi minha primeira oportunidade de ser dono de um produto inteiro, da arquitetura ao deploy. Ele vai além do LinkedIn para alcançar um público internacional, busca oportunidades no exterior e demonstra que Domain-Driven Design e Arquitetura Limpa se sustentam em um projeto solo do zero, não apenas em times onde o processo é imposto por revisão.

As Restrições

A arquitetura foi autoimposta. Sem equipe, sem prazo e sem pressão externa, a restrição veio de uma decisão deliberada: tratar o projeto como um produto real com escopo de MVP, um roadmap pós-MVP e nenhum atalho na camada de domínio.

Performance foi o que mais pesou. O site precisava aguentar o escrutínio do Lighthouse, porque um portfólio lento passa a mensagem errada. O conteúdo também precisava mudar sem deploy, então entradas de projetos e experiências são orientadas por um banco de dados seedado e renderizadas como markdown em vez de fixas no código.

O i18n atravessou as duas frentes. Suportar inglês, português e espanhol significava resolver internacionalização na camada de domínio, não remendá-la na UI depois.

O design visual foi criado inteiramente no Figma por Milena Kawai, uma amiga designer que entregou a especificação completa do zero.

Processo de Engenharia

O backlog foi gerenciado com Task Master, dividido em sprints rastreadas como milestones do GitHub. O GitHub Projects forneceu um quadro Kanban para acompanhamento; cada issue seguia um template estruturado com contexto, critérios de aceitação, arquivos relevantes e dependências. Labels customizadas organizaram o trabalho por sprint, prioridade e tipo.

O projeto foi estruturado em cinco PRDs numerados, um por camada de arquitetura:

  • Sprint 0: fundação do domínio (core): padrão Either, Value Objects, entidades, interfaces de repositório
  • Sprint 1: camada de aplicação: use cases, ports, DTOs
  • Sprint 2: infraestrutura: repositórios Prisma, gateway Supabase, contêiner de DI
  • Sprint 3: site público: Next.js App Router, SSG, roteamento i18n, componentes de UI
  • Sprint 4: CI/CD: verificação de tipos, lint e suite de testes no GitHub Actions

Uma sprint dedicada à acessibilidade resolveu 88 problemas de WCAG, seguida por uma passagem orientada pelo Lighthouse que focou no bundle crítico, hints de preload de RSC e carregamento da imagem LCP.

A pasta docs/ contém 12 documentos de arquitetura numerados: contextos delimitados, estratégia de validação, abordagem de i18n, estratégia de testes, padrões de código e glossário de domínio. Foram escritos conforme o sistema era construído, não depois.

Arquitetura

O domínio é organizado em três contextos delimitados: portfolio (projetos, experiências, skills, perfil), identity (autenticação e usuário) e contact (envio de mensagens). Cada um tem suas próprias entidades, value objects e interfaces de repositório, compartilhando apenas o Shared Kernel.

Cada pacote tem uma única responsabilidade aplicada mecanicamente:

  • core: modelo de domínio; zero dependências de framework; entidades, value objects, padrão Either, interfaces de repositório
  • application: use cases e ports; depende apenas de core; sem Prisma, sem HTTP
  • infra: implementações concretas; única camada que importa Prisma e Supabase
  • ui: biblioteca de componentes React; dividida em View (exibição) e Control (interatividade)
  • utils: utilitários TypeScript puros: Validator, formatadores, hooks de browser; sem dependência de React

Site do Portfólio

Server Components chamam use cases diretamente no build time. Não existe nenhuma camada REST entre o domínio e o HTML gerado; para um site estático orientado a conteúdo, uma fronteira HTTP seria overhead puro.

A internacionalização é uma preocupação de domínio: LocalizedText é um value object em core. O site renderiza em inglês, português e espanhol, tudo resolvido na camada de domínio antes que qualquer componente React toque os dados.

Cada página exporta generateMetadata com title, description e campos openGraph localizados. Páginas de projetos derivam os dados de OG diretamente das entidades de domínio: título, caption, imagem de capa. Os metadados nunca ficam fora de sincronia com o conteúdo. Uma rota de imagem OG personalizada, construída com next/og no Edge Runtime, gera cards 1200×630 com identidade visual por página, locale e projeto.

As rotas de detalhe de projeto são orientadas pelo Slug, um value object em core, com generateStaticParams resolvendo cada slug de projeto publicado nas três locales no build time. Sem slug, sem rota.

O formulário de contato passa por rate limiting via Upstash Redis e entrega e-mail pelo Resend, ambos por trás de interfaces de porta que os mantêm substituíveis e testáveis sem tocar a infraestrutura.

Este portfólio é a primeira presença técnica pública que construí e possuo por completo, do modelo de domínio ao pipeline de deploy. O app admin para gerenciamento de conteúdo e o blog estão escopados como pós-MVP, mantendo o site atual focado e publicável.

Destaques Técnicos

  • Sem camada de API: Server Components consomem use cases no build time; um site estático não precisa de uma fronteira HTTP entre domínio e HTML
  • Direção de dependência aplicada pelo ESLint: violações de camada são detectadas no lint time, não no code review

Erros de domínio nunca lançam exceção. O padrão Either propaga Left<ValidationError> pelos use cases até a UI, mantendo todos os caminhos de erro explícitos e testáveis. O LocalizedText segue a mesma lógica como value object: i18n é uma preocupação de domínio, então componentes recebem strings já resolvidas, não chaves de tradução.

  • Acessibilidade como sprint: 88 problemas de WCAG rastreados, escopados e entregues como issues individuais com critérios de aceitação
  • Performance orientada pelo Lighthouse: bundle crítico enxugado com lazy-loading de formulários pesados, remoção de 'use client' desnecessários e preload da imagem LCP com fetchpriority=high
  • SEO e Open Graph: cada página exporta generateMetadata localizado. Uma rota /og no Edge Runtime gera cards 1200×630 por página, locale e projeto usando next/og, com dados de OG derivados das entidades de domínio em vez de strings estáticas

Tecnologias

  • Next.js: App Router com SSG; generateStaticParams gera todas as rotas localizadas no build time
  • Turborepo: orquestração de monorepo com cinco pacotes compartilhados e cache remoto no Vercel
  • TypeScript: modo strict em todos os pacotes; any é proibido
  • Prisma: ORM e camada de migrations, isolado em packages/infra
  • Supabase: banco de dados PostgreSQL e autenticação baseada em JWT
  • Tailwind CSS: tokens de design compartilhados via packages/tailwind-config
  • next-intl: roteamento de locale e resolução de mensagens para EN, PT-BR e ES
  • Vitest: testes unitários e de integração em todos os pacotes; ~100 arquivos de teste
  • Upstash Redis: rate limiting serverless no formulário de contato
  • Resend: e-mail transacional para envios do formulário de contato
  • Vercel: deployment com cache remoto do Turborepo

Outros projetos

  • Plataforma B2B TC Representações: loja atacadista restrita para materiais de construção

    Plataforma B2B de E-Commerce

    Plataforma B2B full-stack para materiais de construção, com Arquitetura Limpa, React e Node.js, do zero à produção.

    • TypeScript
    • React
    Ver projeto