From ea05ce4a5f0108751da42ea282e17742a6c36bac Mon Sep 17 00:00:00 2001 From: Evandro Fonseca Junior Date: Tue, 13 Oct 2026 21:48:04 -0300 Subject: [PATCH] =?UTF-8?q?docs:=20redesign=20do=20README=20(padr=C3=A3o?= =?UTF-8?q?=20TwitterBR-MOD)=20=E2=80=94=20dados=20atualizados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 251 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 166 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index a86d8de..bd77dd9 100644 --- a/README.md +++ b/README.md @@ -1,112 +1,144 @@
-# Evandro.dev.br: portfólio +Logo do Evandro.dev.br -Portfólio profissional de Evandro Fonseca Junior, com projetos, cases, serviços, currículo e contato por WhatsApp. +# 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)
-## Requisitos +> [!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). -- Node.js `22.x` -- pnpm `9.15.9`, fixado em `package.json#packageManager` +> [!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 projeto usa Next.js `16.3.0`. Essa versão é intencional: `16.2.11` ainda mantinha três advisories transitivos de severidade alta; `16.3.0` foi a menor versão estável da mesma major que deixou as auditorias atuais sem vulnerabilidades high. - -## Início rápido - -```bash -corepack pnpm@9.15.9 install --frozen-lockfile -corepack pnpm@9.15.9 dev -``` - -O servidor de desenvolvimento usa Turbopack. Para executar o artefato de produção: - -```bash -corepack pnpm@9.15.9 build -corepack pnpm@9.15.9 start -``` - -## Scripts - -| Comando | 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`. | - -## Stack - -| Á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. - -## Rotas +## 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`. | +| `/` | 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. +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 `
` nativo. Sobre e Contato apontam para `/#about` e `/#contact`, com ajuste de chegada após a definição do layout do notebook. +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 `
` nativo. Sobre e +Contato apontam para `/#about` e `/#contact`, com ajuste de chegada após a +definição do layout do notebook. -## Comportamento da aplicação +## Como funciona -### Conteúdo e project health +```mermaid +flowchart LR + A["public/portfolio-data.json
+ lib/site-content.ts"] --> B["lib/portfolio-data.ts
loadFeaturedProjects()"] + C["data/project-health.json
snapshot versionado"] --> B + D["scripts/check-projects.mjs
pnpm check:projects"] -->|rename atômico| C + B --> E["app/ — App Router
homepage, cases, serviços"] + E --> F["Next.js 16.3.0
build e start (Turbopack)"] +``` -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. +
+Conteúdo e project health -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). +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. -### 3D progressivo e movimento reduzido +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). -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. +
+3D progressivo e movimento reduzido -### Contato +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. -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. +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. -### Consentimento de analytics +
-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. +
+Contato e consentimento de analytics -## Estrutura +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. ```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 modelo 3D +public/ Conteúdo JSON, PDF, fontes, imagens e capturas scripts/check-projects.mjs Atualização manual do snapshot de demos data/project-health.json @@ -114,16 +146,47 @@ data/project-health.json 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 +nixpacks.toml Build e start para Nixpacks ``` -## CI e deploy +
-O workflow único em `.github/workflows/ci.yml` roda em cada `push` e `pull_request` com permissão `contents: read`. 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. +## Limitações conhecidas -O Nixpacks 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. +- **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. -## Validação local +## 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 pnpm@9.15.9 install --frozen-lockfile +corepack pnpm@9.15.9 dev # Next.js com Turbopack +corepack pnpm@9.15.9 build # build de produção com Turbopack +corepack pnpm@9.15.9 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 pnpm@9.15.9 install --frozen-lockfile @@ -134,3 +197,21 @@ corepack pnpm@9.15.9 build corepack pnpm@9.15.9 audit --prod --audit-level=high corepack pnpm@9.15.9 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).