docs(readme): padroniza README (hero, badges, quickstart, arquitetura)
This commit is contained in:
1 parent
34c7eb7f8c
commit
594daecd2b
1 file changed
+168
-169
@@ -2,187 +2,176 @@
|
|||||||
|
|
||||||
<img src="public/edev_logo.svg" width="110" alt="Logo do Evandro.dev.br">
|
<img src="public/edev_logo.svg" width="110" alt="Logo do Evandro.dev.br">
|
||||||
|
|
||||||
# Evandro.dev.br — portfólio
|
<h1>Evandro Fonseca Junior</h1>
|
||||||
|
|
||||||
**Portfólio profissional de Evandro Fonseca Junior: projetos, cases, serviços,
|
<p><strong>Engenheiro da Computação em Garuva-SC: sites, sistemas web e revisão de apps feitos com IA, com contato direto pelo WhatsApp.</strong></p>
|
||||||
currículo e contato por WhatsApp — com hero e notebook 3D progressivos que caem
|
|
||||||
para HTML puro quando o dispositivo não comporta.**
|
|
||||||
|
|
||||||

|
<a href="https://evandro.dev.br">Site</a> ·
|
||||||

|
<a href="https://evandro.dev.br/cases">Cases</a> ·
|
||||||

|
<a href="https://evandro.dev.br/curriculo">Currículo</a> ·
|
||||||
|
<a href="#-quickstart">Quickstart</a> ·
|
||||||
|
<a href="#-arquitetura">Arquitetura</a> ·
|
||||||
|
<a href="https://www.linkedin.com/in/evandrodevbr/">LinkedIn</a> ·
|
||||||
|
<a href="https://git.evandro.dev.br/evandro/portifolio-evandrodevbr/issues">Issues</a>
|
||||||
|
|
||||||
[Rotas](#o-que-o-site-entrega) · [Como funciona](#como-funciona) · [Execução local](#execu%C3%A7%C3%A3o-local) · [CI/CD](#cicd)
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
> [!NOTE]
|
<hr />
|
||||||
> **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]
|
## 📌 O problema
|
||||||
> **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
|
Pequenos negócios costumam vender e atender por mensagem: o cliente pergunta o preço um a um, o estoque vive em planilha e qualquer mudança no site depende de um desenvolvedor. Este repositório é o site [evandro.dev.br](https://evandro.dev.br), a vitrine de quem resolve isso: projetos entregues, serviços, currículo e um botão de WhatsApp para começar a conversa.
|
||||||
|
|
||||||
| Rota | Conteúdo |
|
## ✨ O que faz
|
||||||
|
|
||||||
|
- Apresenta três ofertas: criação de sites, sistemas web sob medida e revisão de apps feitos com IA (`/ia`).
|
||||||
|
- Publica oito cases com stack, entregas e decisões técnicas, cada um em `/cases/<id>`.
|
||||||
|
- Detalha seis serviços em `/servicos/*`, com escopo e etapas visíveis e a parte técnica em `<details>`.
|
||||||
|
- Serve o currículo em HTML e o PDF em `/Profile.pdf`.
|
||||||
|
- Abre o `wa.me` com o briefing já preenchido a partir do formulário de contato; não há backend de formulário.
|
||||||
|
- Mostra o hero e o notebook de projetos em 3D (Three.js) só onde o dispositivo comporta; nos demais, entrega HTML estático.
|
||||||
|
- Carrega Google Analytics somente depois de aceite explícito, e permite revogar o consentimento depois.
|
||||||
|
- Gera `sitemap.xml`, `robots.txt`, manifest, imagens Open Graph e dados estruturados JSON-LD.
|
||||||
|
|
||||||
|
### Cases publicados
|
||||||
|
|
||||||
|
Fonte: `public/portfolio-data.json` e `lib/site-content.ts` (os mesmos oito ids).
|
||||||
|
|
||||||
|
| Case | O que é | Estado | Demo |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| [`sev-modaintima`](https://evandro.dev.br/cases/sev-modaintima) | SEV Moda Íntima: catálogo digital e loja virtual, pedido pelo WhatsApp e painel de estoque | Em produção | [sevmodaintima.com.br](https://sevmodaintima.com.br) |
|
||||||
|
| [`lavacao-047`](https://evandro.dev.br/cases/lavacao-047) | Lavação 047: site e painel para lavação automotiva em Garuva-SC, o dono edita preços, textos e fotos | Em produção | [landing-page-lavacao047.vercel.app](https://landing-page-lavacao047.vercel.app) |
|
||||||
|
| [`nutriscan`](https://evandro.dev.br/cases/nutriscan) | NutriScan: consulta de produtos por nome e código de barras | Em produção | [nutriscan.evandro.dev.br](https://nutriscan.evandro.dev.br) |
|
||||||
|
| [`twins-lab`](https://evandro.dev.br/cases/twins-lab) | Twins Lab: painel ao vivo de um reator simulado | Protótipo | sem demo |
|
||||||
|
| [`reddit-explorer`](https://evandro.dev.br/cases/reddit-explorer) | Reddit Posts Explorer: posts de um fórum de IA, filtrados por período | Concluído | sem demo |
|
||||||
|
| [`sc-plus`](https://evandro.dev.br/cases/sc-plus) | SC Plus Aquicultura: site institucional com áreas, projetos e contato | Concluído | [scplus.evandro.dev.br](https://scplus.evandro.dev.br) |
|
||||||
|
| [`gcc-installer`](https://evandro.dev.br/cases/gcc-installer) | MinGW GCC Installer: instalador do compilador GCC para Windows | Concluído | sem demo |
|
||||||
|
| [`as-servicos`](https://evandro.dev.br/cases/as-servicos) | AS Serviços: site institucional com cena 3D | Concluído | sem demo |
|
||||||
|
|
||||||
|
## 🖼️ Demonstração
|
||||||
|
|
||||||
|
| SEV Moda Íntima | NutriScan |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `/` | Homepage com hero, notebook de projetos, perfil, competências, experiência, projetos, modalidades de trabalho e contato |
|
| <img src="./public/assets/prints/print-sev.png" width="380" alt="Site da SEV Moda Íntima"> | <img src="./public/assets/prints/print-nutriscan.png" width="380" alt="NutriScan"> |
|
||||||
| `/cases` | Índice dos seis cases |
|
| **SC Plus Aquicultura** | **AS Serviços** |
|
||||||
| `/cases/nutriscan` | Case NutriScan |
|
| <img src="./public/assets/prints/print-scplus.png" width="380" alt="Site da SC Plus Aquicultura"> | <img src="./public/assets/prints/print-asservicos.png" width="380" alt="Site da AS Serviços"> |
|
||||||
| `/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`,
|
Capturas feitas com Chrome headless a partir de deploys de produção do próprio autor. Origem e créditos (inclusive do ícone do WhatsApp) em [`CREDITS.md`](CREDITS.md).
|
||||||
`/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;
|
## 🚀 Quickstart
|
||||||
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
|
| Ferramenta | Versão mínima |
|
||||||
|
|
||||||
```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 |
|
| Node.js | `22.x` (`engines`) |
|
||||||
| Estilos | Tailwind CSS 4 |
|
| pnpm | `9.15.9` (`packageManager`) |
|
||||||
| Movimento | CSS (`animation-timeline`) e Lenis |
|
| Chromium | só para `pnpm test:e2e` (Playwright) |
|
||||||
| 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
|
```bash
|
||||||
corepack [email protected] install --frozen-lockfile
|
corepack [email protected] install --frozen-lockfile
|
||||||
corepack [email protected] dev # Next.js com Turbopack
|
corepack [email protected] dev # Next.js com Turbopack
|
||||||
corepack [email protected] build # build de produção com Turbopack
|
corepack [email protected] build # build de produção
|
||||||
corepack [email protected] start # serve um build já gerado
|
corepack [email protected] start # serve um build já gerado
|
||||||
```
|
```
|
||||||
|
|
||||||
| Script | Comportamento |
|
A instalação é sempre com `--frozen-lockfile`, igual ao CI e ao Nixpacks.
|
||||||
|
|
||||||
|
Não há `.env.example` e nenhuma variável é necessária para rodar localmente. As que o código lê:
|
||||||
|
|
||||||
|
| Variável | Obrigatória | Descrição |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `NEXT_PUBLIC_GOOGLE_ADS_CONVERSION_LABEL` | Não | Rótulo de conversão do Google Ads; sem ele, nenhum evento de conversão é enviado |
|
||||||
|
| `BASE_URL` | Não | Endereço do site testado por `pnpm test:e2e` (padrão `http://localhost:3001`) |
|
||||||
|
| `PW_CHROMIUM` | Não | Caminho de um Chromium local para o Playwright, para não baixar o navegador |
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> O Next.js (`16.3.8`) é fixado de propósito: a `16.2.11` mantinha três advisories transitivos de severidade alta, e a `16.3.0` foi a menor versão estável da mesma major que deixou as auditorias sem vulnerabilidades high. Não faça downgrade sem repetir `pnpm audit`.
|
||||||
|
|
||||||
|
## 🧱 Arquitetura
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart LR
|
||||||
|
A["public/portfolio-data.json"] --> B["lib/portfolio-data.server.ts"]
|
||||||
|
S["lib/site-content.ts"] --> E["app/ App Router"]
|
||||||
|
C["data/project-health.json"] --> B
|
||||||
|
D["scripts/check-projects.mjs"] -->|rename atômico| C
|
||||||
|
B --> E
|
||||||
|
E --> F["Vercel"]
|
||||||
|
```
|
||||||
|
|
||||||
|
- O conteúdo vem de `public/portfolio-data.json` e `lib/site-content.ts`; a homepage escolhe os projetos pelo campo `featured`.
|
||||||
|
- `data/project-health.json` é um snapshot versionado das demos. Ele só controla o CTA de cada card (disponível, indisponível, desconhecido ou sem demo) e nunca remove um card.
|
||||||
|
- Em produção, o render só lê o snapshot e não consulta demos externas. Em desenvolvimento, um snapshot ausente ou com mais de 15 minutos é atualizado em memória.
|
||||||
|
- `pnpm check:projects` atualiza o snapshot por rename atômico. Contrato completo em [`docs/project-health.md`](docs/project-health.md).
|
||||||
|
- Não há API route ativa.
|
||||||
|
|
||||||
|
### CI/CD
|
||||||
|
|
||||||
|
Um único workflow, [`.gitea/workflows/ci.yml`](.gitea/workflows/ci.yml), roda em `push`, `pull_request` e `workflow_dispatch`, com permissão `contents: read`. O repositório usa Gitea; por isso não há badge de GitHub Actions.
|
||||||
|
|
||||||
|
| Job | O que roda | Bloqueia o deploy |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `verify` | Node 22, `pnpm install --frozen-lockfile`, `lint`, `typecheck`, `test -- --runInBand`, `build` | Sim |
|
||||||
|
| `audit` | `pnpm audit --prod` e `pnpm audit --dev`, ambos com `--audit-level=high` | Não |
|
||||||
|
| `e2e` | Playwright (Chromium) contra o build de produção na porta 3001; publica `test-results/` | Não |
|
||||||
|
| `deploy` | Vercel CLI `61.1.0`; só após `verify`; branch padrão vai para produção, as demais para preview; pull request não publica | n/a |
|
||||||
|
|
||||||
|
O deploy usa o secret `VERCEL_TOKEN`; o projeto na Vercel é o nome do repositório, ou a variável `VERCEL_PROJECT`. [`nixpacks.toml`](nixpacks.toml) (`nodejs_22`, `pnpm-9_x`) e [`vercel.json`](vercel.json) (`framework: nextjs`) descrevem o build.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Rotas</summary>
|
||||||
|
|
||||||
|
| Rota | Conteúdo |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `pnpm dev` | Inicia o Next.js em desenvolvimento com Turbopack |
|
| `/` | Hero, notebook de projetos, perfil, competências, experiência, projetos, modalidades de trabalho e contato |
|
||||||
| `pnpm build` | Gera o build de produção com Turbopack |
|
| `/cases`, `/cases/<id>` | Índice e página de cada um dos oito cases |
|
||||||
|
| `/servicos` | Índice dos seis serviços |
|
||||||
|
| `/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 |
|
||||||
|
| `/servicos/integracao-hardware-software-iot` | Integração de hardware, software e IoT |
|
||||||
|
| `/servicos/arquitetura-de-software` | Diagnóstico de arquitetura |
|
||||||
|
| `/ia` | Revisão de sistema e de app feito com IA |
|
||||||
|
| `/curriculo` | Currículo em HTML, com download de `/Profile.pdf` |
|
||||||
|
| `/privacidade` | Privacidade e consentimento de analytics |
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
## 🗂️ Estrutura
|
||||||
|
|
||||||
|
```text
|
||||||
|
app/ rotas (App Router) e componentes
|
||||||
|
lib/ conteúdo (site-content.ts), SEO, JSON-LD, WhatsApp, project health
|
||||||
|
public/ portfolio-data.json, Profile.pdf, logos, capturas e mídias dos cases
|
||||||
|
data/ project-health.json, snapshot versionado das demos
|
||||||
|
scripts/ check-projects.mjs e utilitários de SEO e vídeo
|
||||||
|
e2e/ testes Playwright (9 specs)
|
||||||
|
docs/ SEO/GEO, project health e planos
|
||||||
|
.gitea/workflows/ ci.yml (verify, audit, e2e, deploy)
|
||||||
|
nixpacks.toml build e start via Nixpacks
|
||||||
|
CREDITS.md créditos de capturas e ícone
|
||||||
|
```
|
||||||
|
|
||||||
|
Stack: Next.js 16.3.8, React 19.1.0, TypeScript 5.9.2, Tailwind CSS 4, Three.js, Lenis e Lucide React. Qualidade: Biome, Jest 30 com Testing Library (150 arquivos de teste), Playwright e axe-core. Todas as dependências diretas estão fixadas em versões exatas, exceto `lenis` (`^1.3.26`).
|
||||||
|
|
||||||
|
## 🧪 Scripts
|
||||||
|
|
||||||
|
| Comando | O que faz |
|
||||||
|
| --- | --- |
|
||||||
|
| `pnpm dev` | Next.js em desenvolvimento com Turbopack |
|
||||||
|
| `pnpm build` | Build de produção com Turbopack |
|
||||||
| `pnpm start` | Serve um build já gerado |
|
| `pnpm start` | Serve um build já gerado |
|
||||||
| `pnpm lint` | Executa `biome check` |
|
| `pnpm lint` | Executa `biome check` |
|
||||||
| `pnpm typecheck` | Executa TypeScript sem emitir arquivos |
|
| `pnpm typecheck` | Executa `next typegen` e `tsc --noEmit` |
|
||||||
| `pnpm format` | Formata o repositório com Biome |
|
| `pnpm format` | Formata o repositório com Biome |
|
||||||
| `pnpm test` | Executa a suíte Jest |
|
| `pnpm test` | Executa a suíte Jest |
|
||||||
| `pnpm test:watch` | Executa Jest em modo watch |
|
| `pnpm test:watch` | Executa Jest em modo watch |
|
||||||
| `pnpm check:projects` | Verifica URLs de demonstração e substitui atomicamente `data/project-health.json` |
|
| `pnpm test:e2e` | Executa o Playwright contra um servidor já no ar (`BASE_URL`) |
|
||||||
|
| `pnpm check:projects` | Consulta as demos e substitui atomicamente `data/project-health.json` |
|
||||||
|
|
||||||
Validação completa, na mesma ordem do CI:
|
Validação completa, na mesma ordem do CI:
|
||||||
|
|
||||||
@@ -196,20 +185,30 @@ corepack [email protected] audit --prod --audit-level=high
|
|||||||
corepack [email protected] audit --dev --audit-level=high
|
corepack [email protected] audit --dev --audit-level=high
|
||||||
```
|
```
|
||||||
|
|
||||||
## CI/CD
|
Para os testes de ponta a ponta: `pnpm build && pnpm start -p 3001`, e em outro terminal `BASE_URL=http://localhost:3001 pnpm test:e2e`.
|
||||||
|
|
||||||
O workflow único [`.github/workflows/ci.yml`](.github/workflows/ci.yml) roda em
|
## 📚 Documentação
|
||||||
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`,
|
- [`docs/project-health.md`](docs/project-health.md): estados do CTA das demos e atualização do snapshot.
|
||||||
`pnpm install --frozen-lockfile`, `pnpm run build` e `pnpm run start`. Não há
|
- [`docs/seo-geo-operations.md`](docs/seo-geo-operations.md): runbook de SEO e GEO (Search Console, Bing, Cloudflare, CrUX), descrito e **não executado**.
|
||||||
etapa de deploy nem secret de CI neste repositório.
|
- [`docs/seo-geo-validation.md`](docs/seo-geo-validation.md): validação de SEO e GEO.
|
||||||
|
- [`CREDITS.md`](CREDITS.md): créditos das capturas de tela e do ícone do WhatsApp.
|
||||||
|
|
||||||
## Avisos
|
## 🛣️ Limitações e próximos passos
|
||||||
|
|
||||||
- As capturas em `public/assets/prints/*.png` foram feitas com Chrome headless a
|
- **Sem backend.** O formulário de contato não grava nada: abre `wa.me` com o briefing preenchido, e o rodapé mantém o contato direto por e-mail.
|
||||||
partir de deploys de produção do próprio autor (evandro.dev.br) e aparecem como
|
- **Demos externas podem aparecer como indisponíveis.** O CTA reflete o último snapshot versionado, não uma consulta em tempo real. No snapshot de 2026-07-11, só a SEV respondeu 200; `nutriscan` falhou na consulta e `sc-plus` respondeu 502. Rode `pnpm check:projects` para renová-lo.
|
||||||
conteúdo da tela do notebook. Detalhes em [`CREDITS.md`](CREDITS.md).
|
- **Sem 3D em telas pequenas, com ponteiro `coarse` ou movimento reduzido.** O hero e o notebook entregam a versão HTML.
|
||||||
|
- **Ações externas de SEO/GEO pendentes.** Search Console, Bing, Cloudflare e CrUX estão só no runbook.
|
||||||
|
|
||||||
|
## 🤝 Contribuindo
|
||||||
|
|
||||||
|
Projeto pessoal (`"private": true` no `package.json`). O CI roda em `push` e `pull_request`; antes de abrir um PR, o que ele exige deve passar localmente:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm lint && pnpm typecheck && pnpm test -- --runInBand && pnpm build
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📄 Licença
|
||||||
|
|
||||||
|
Sem licença definida — todos os direitos reservados.
|
||||||
Reference in new issue
Block a user