Files
portifolio-evandrodevbr/README.md
T
Evandro Fonseca Junior 34c7eb7f8c
CI / e2e (push) Failing after 6m52s
CI / verify (push) Failing after 6m59s
CI / deploy (push) Skipped
CI / audit (push) Successful in 10m17s
merge: integra o deploy da Vercel e unifica CI e deploy num pipeline
Traz da main do Gitea o deploy pela Vercel (vercel.json) e o README redesenhado, atualizado para a stack atual (sem Motion, GSAP, React Three Fiber, Drei, Cobe, clsx e tailwind-merge). CI e deploy passam a viver em .gitea/workflows/ci.yml, porque o Gitea ignora .github/workflows quando .gitea/workflows existe: verify (lint, tipos, testes, build) -> deploy na Vercel (padrão -> produção, demais -> preview, PR não publica); audit e e2e em jobs próprios. Vercel CLI fixo em 61.1.0.
2026-10-15 00:27:00 -03:00

216 lines
9.3 KiB
Markdown

<div align="center">
<img src="public/edev_logo.svg" width="110" alt="Logo do Evandro.dev.br">
# 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.**
![Next.js](https://img.shields.io/badge/Next.js-16.3.0-informational)
![React](https://img.shields.io/badge/React-19.1.0-informational)
![Node](https://img.shields.io/badge/Node-22.x-informational)
[Rotas](#o-que-o-site-entrega) · [Como funciona](#como-funciona) · [Execução local](#execu%C3%A7%C3%A3o-local) · [CI/CD](#cicd)
</div>
> [!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 em `app/sitemap.ts` e `app/robots.ts`. As ações externas
> de SEO/GEO (Search Console, Bing, Cloudflare, CrUX) estão descritas como runbook e
> **não executadas** em [`docs/seo-geo-operations.md`](docs/seo-geo-operations.md).
> [!IMPORTANT]
> **Next.js `16.3.0` é intencional.** A `16.2.11` ainda mantinha três advisories
> transitivos de severidade alta; a `16.3.0` foi a menor versão estável da mesma
> major que deixou as auditorias atuais sem vulnerabilidades high. Não faça
> downgrade sem repetir `pnpm 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
```mermaid
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)"]
```
<details>
<summary>Conteúdo e project health</summary>
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`](docs/project-health.md).
</details>
<details>
<summary>3D progressivo e movimento reduzido</summary>
O fundo 3D do hero (Three.js, sem React Three Fiber) só é montado a partir de
`1024px`, com ponteiro fino, sem `prefers-reduced-motion: reduce`, sem economia
de dados e com placa de vídeo real (WebGL por software mostra o hero estático).
A cena monta depois da primeira interação ou com o navegador ocioso, desenha no
máximo ~30 quadros por segundo e para quando nada se move. No celular e nos
demais casos, o hero é estático e ocupa uma tela.
As passagens entre seções e a barra de progresso são CSS (`animation-timeline`);
a rolagem suave (Lenis) só existe com ponteiro fino.
</details>
<details>
<summary>Contato e consentimento de analytics</summary>
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.
</details>
<details>
<summary>Stack e estrutura</summary>
| Área | Pacotes usados |
| --- | --- |
| Aplicação | Next.js 16.3.8, React 19.1.0, React DOM 19.1.0 e TypeScript 5.9.2 |
| Estilos | Tailwind CSS 4 |
| Movimento | CSS (`animation-timeline`) e Lenis |
| 3D | Three.js |
| Interface | Lucide React |
| Qualidade | Biome, Jest, Testing Library (JSDOM), Playwright e axe-core |
Todas as dependências diretas estão fixadas em versões exatas no manifesto; o
lockfile é instalado sem atualização implícita.
```text
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
```
</details>
## Limitações conhecidas
- **Sem backend.** O formulário de contato não grava nada: abre `wa.me` com 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.x`** e **pnpm `9.15.9`** (fixado em `package.json#packageManager`).
> A instalação é sempre com `--frozen-lockfile`; o CI e o Nixpacks fazem o mesmo.
```bash
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:
```bash
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`](.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`](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/*.png` foram 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 em [`CREDITS.md`](CREDITS.md).