Evandro.dev.br — portfólio
Portfólio profissional de Evandro Fonseca Junior: projetos, cases, serviços, currículo e contato por WhatsApp — com hero e notebook 3D progressivos que caem para HTML puro quando o dispositivo não comporta.
Note
Estado do projeto: em desenvolvimento ativo (último commit: "refine portfolio showcase, services and quality lab"); o site de produção é
https://evandro.dev.br, que é o host declarado emapp/sitemap.tseapp/robots.ts. As ações externas de SEO/GEO (Search Console, Bing, Cloudflare, CrUX) estão descritas como runbook e não executadas emdocs/seo-geo-operations.md.
Important
Next.js
16.3.0é intencional. A16.2.11ainda mantinha três advisories transitivos de severidade alta; a16.3.0foi a menor versão estável da mesma major que deixou as auditorias atuais sem vulnerabilidades high. Não faça downgrade sem repetirpnpm audit.
O que o site entrega
| Rota | Conteúdo |
|---|---|
/ |
Homepage com hero, notebook de projetos, perfil, competências, experiência, projetos, modalidades de trabalho e contato |
/cases |
Índice dos seis cases |
/cases/nutriscan |
Case NutriScan |
/cases/twins-lab |
Case Twins Lab |
/cases/reddit-explorer |
Case Reddit Posts Explorer |
/cases/sc-plus |
Case SC Plus Aquicultura |
/cases/gcc-installer |
Case MinGW GCC Installer |
/cases/as-servicos |
Case AS Serviços |
/servicos |
Índice dos seis serviços, com explicações de uso e acesso ao detalhamento técnico |
/servicos/criacao-de-sites |
Criação de sites |
/servicos/engenharia-de-software |
Sistemas web e aplicativos mobile sob medida |
/servicos/consultoria-nextjs |
Consultoria Next.js |
/servicos/tauri-rust |
Aplicativos desktop para Windows e Linux, com compatibilidade definida por projeto |
/servicos/integracao-hardware-software-iot |
Integração de hardware, software e IoT |
/servicos/arquitetura-de-software |
Arquitetura de software |
/curriculo |
Currículo em HTML, com download de /Profile.pdf |
/privacidade |
Página de privacidade e consentimento de analytics |
O App Router também gera /manifest.webmanifest, /robots.txt, /sitemap.xml,
/opengraph-image, /icon.svg e /favicon.ico. Caminhos desconhecidos usam a
página 404 do projeto. Não há API route ativa.
As páginas de serviços mantêm escopo, exemplos ilustrativos e etapas visíveis;
tecnologias e decisões de implementação ficam em um <details> nativo. Sobre e
Contato apontam para /#about e /#contact, com ajuste de chegada após a
definição do layout do notebook.
Como funciona
flowchart LR
A["public/portfolio-data.json<br/>+ lib/site-content.ts"] --> B["lib/portfolio-data.ts<br/>loadFeaturedProjects()"]
C["data/project-health.json<br/>snapshot versionado"] --> B
D["scripts/check-projects.mjs<br/>pnpm check:projects"] -->|rename atômico| C
B --> E["app/ — App Router<br/>homepage, cases, serviços"]
E --> F["Next.js 16.3.0<br/>build e start (Turbopack)"]
Conteúdo e project health
O conteúdo principal vem de public/portfolio-data.json e lib/site-content.ts.
A seleção da homepage usa o campo featured; o snapshot de disponibilidade não
remove cards. Ele apenas controla o estado do CTA de cada demo: disponível,
indisponível, desconhecido ou sem demo.
Em produção, a renderização só lê o snapshot versionado e não consulta demos
externas. Em desenvolvimento, um snapshot ausente ou com mais de 15 minutos é
atualizado em memória. A atualização manual opcional é pnpm check:projects e
grava o arquivo por rename atômico. O contrato completo está em
docs/project-health.md.
3D progressivo e movimento reduzido
O hero 3D é carregado no cliente a partir de 1024px, sem
prefers-reduced-motion: reduce e sem ponteiro coarse. O notebook 3D exige mais
de 1024px, hover disponível e as mesmas condições de movimento e ponteiro. Nos
demais casos, o notebook entrega a navegação HTML completa sem WebGL ou
movimento. No desktop, tampa, tela, abas e cursor seguem o mesmo progresso de
scroll; a cena renderiza sob demanda e pausa fora do viewport ou com a página
oculta.
As quatro capturas desktop reais ficam em public/assets/notebook/, em WebP de
1600 × 1000. A troca aguarda a decodificação da próxima imagem, mantendo a
anterior visível durante o carregamento ou uma falha.
Contato e consentimento de analytics
O formulário da homepage valida os campos nativos de nome, e-mail, tipo e
contexto. Ao enviar, ele abre wa.me em uma nova aba com o briefing
preenchido; não existe backend de formulário. O rodapé mantém contato direto por
e-mail.
Google Analytics só é carregado depois de aceite explícito. A decisão fica em
evandro.analytics-consent.v1; recusar não monta o loader. As preferências
permanecem acessíveis e a revogação envia consentimento negado, ativa a flag de
desabilitação, remove o loader e expira apenas cookies _ga/_ga_*
acessíveis.
Stack e estrutura
| Área | Pacotes usados |
|---|---|
| Aplicação | Next.js 16.3.0, React 19.1.0, React DOM 19.1.0 e TypeScript 5.9.2 |
| Estilos e composição | Tailwind CSS 4, clsx e tailwind-merge |
| Movimento | Motion 12 e GSAP 3 |
| 3D e gráficos | Three.js, React Three Fiber, Drei e Cobe |
| Interface | Lucide React |
| Qualidade | Biome, Jest, Testing Library e ambiente JSDOM |
Todas as dependências diretas estão fixadas em versões exatas no manifesto; o lockfile é instalado sem atualização implícita.
app/ App Router, rotas e componentes da interface
lib/ Dados derivados, navegação, JSON-LD e project health
public/ Conteúdo JSON, PDF, fontes, imagens e capturas
scripts/check-projects.mjs
Atualização manual do snapshot de demos
data/project-health.json
Última observação versionada das demos
docs/project-health.md Contrato operacional do snapshot
.github/workflows/ci.yml
Gate único de integração contínua
nixpacks.toml Build e start para Nixpacks
Limitações conhecidas
- Sem backend. O formulário de contato não grava nada: abre
wa.mecom o briefing preenchido. - Demos externas podem aparecer como indisponíveis. O CTA de cada case reflete
o último snapshot versionado em
data/project-health.json, não uma consulta em tempo real (em produção o render não faz fetch externo). - Sem WebGL em telas pequenas, com ponteiro coarse ou movimento reduzido. Nesses casos o hero e o notebook entregam a versão HTML.
Execução local
Warning
Use Node.js
22.xe pnpm9.15.9(fixado empackage.json#packageManager). A instalação é sempre com--frozen-lockfile; o CI e o Nixpacks fazem o mesmo.
corepack [email protected] install --frozen-lockfile
corepack [email protected] dev # Next.js com Turbopack
corepack [email protected] build # build de produção com Turbopack
corepack [email protected] start # serve um build já gerado
| Script | Comportamento |
|---|---|
pnpm dev |
Inicia o Next.js em desenvolvimento com Turbopack |
pnpm build |
Gera o build de produção com Turbopack |
pnpm start |
Serve um build já gerado |
pnpm lint |
Executa biome check |
pnpm typecheck |
Executa TypeScript sem emitir arquivos |
pnpm format |
Formata o repositório com Biome |
pnpm test |
Executa a suíte Jest |
pnpm test:watch |
Executa Jest em modo watch |
pnpm check:projects |
Verifica URLs de demonstração e substitui atomicamente data/project-health.json |
Validação completa, na mesma ordem do CI:
corepack [email protected] install --frozen-lockfile
corepack [email protected] lint
corepack [email protected] typecheck
corepack [email protected] test -- --runInBand
corepack [email protected] build
corepack [email protected] audit --prod --audit-level=high
corepack [email protected] audit --dev --audit-level=high
CI/CD
O workflow único .github/workflows/ci.yml roda em
cada push e pull_request, com permissão contents: read. No job verify
(ubuntu-latest) ele instala Node 22 e pnpm conforme packageManager, restaura o
cache do pnpm e executa, nesta ordem: frozen install, lint, typecheck, Jest
serial, build e auditorias de produção e desenvolvimento com limite high.
O Nixpacks (nixpacks.toml) usa nodejs_22, pnpm-9_x,
pnpm install --frozen-lockfile, pnpm run build e pnpm run start. Não há
etapa de deploy nem secret de CI neste repositório.
Avisos
- As capturas em
public/assets/prints/*.pngforam feitas com Chrome headless a partir de deploys de produção do próprio autor (evandro.dev.br) e aparecem como conteúdo da tela do notebook. Detalhes emCREDITS.md.