# Auditoria de Performance — Página Inicial (Home)
> Versão: 1.0 · Data: 2026-04-22
> Escopo: `HomePage.tsx`, `HomeScrollScene.tsx`, `AgentsCarousel.tsx`, `PropertyRowCard.tsx`, `Navbar.tsx`
---
## 1. Resumo Executivo
A página inicial é a mais crítica em termos de first impression e conversão. A análise identificou **5 categorias de problemas** que impactam diretamente o Core Web Vitals (LCP, CLS, INP) e a experiência percebida do usuário:
| Categoria | Severidade | Impacto estimado no LCP |
|---|---|---|
| Requests em cascata (waterfall) | 🔴 Alta | +600–1200 ms |
| Imagem hero sem preload / sem dimensões | 🔴 Alta | +800–1500 ms |
| Scroll scene: `useTheme` + re-renders desnecessários | 🟡 Média | +60–150 ms INP |
| AgentsCarousel: autoplay sem `requestAnimationFrame` | 🟡 Média | jank visual |
| `RiseCard`: IntersectionObserver por instância | 🟢 Baixa | +n×2 ms compositing |
---
## 2. Problemas Identificados
### 2.1 Waterfall de Requests (Crítico)
**Arquivo:** `HomePage.tsx` + `HomeScrollScene.tsx`
**Problema atual:**
```
Render HomePage
└─ useEffect: getHomepageConfig() ← request 1 (bloqueia backgroundImage)
└─ setState(config) → re-render
└─ HomeScrollScene recebe props
└─ useEffect: getFeaturedProperties() ← request 2 só começa AQUI
└─ useEffect: getAgents() ← request 3 só começa APÓS mount
```
Os três requests são **seriais por dependência de render**: `getAgents` e `getFeaturedProperties` só disparam após `HomeScrollScene` montar, que depende do render de `HomePage`, que depende de `getHomepageConfig`.
**Impacto:** Em conexões 3G, o usuário espera 3× o RTT antes de ver qualquer conteúdo real. LCP pode ultrapassar 4 s.
**Solução:** Paralelizar os três fetches no topo de `HomePage` com `Promise.all` e passar dados via props.
---
### 2.2 Hero Image sem `` e sem width/height (Crítico)
**Arquivo:** `HomeScrollScene.tsx`, linha da tag ``
**Problema atual:**
```tsx
```
- Sem `width`/`height` → o browser não reserva espaço → **CLS** quando a imagem carrega
- Sem `` no `
` → a imagem começa a baixar somente quando o React renderiza o componente, não durante o parse do HTML
- Sem `fetchpriority="high"` → browser não prioriza sobre outros assets
- Sem `loading="eager"` explícito → comportamento depende do browser
**Impacto:** LCP degradado. Em telas de 1080p com imagem de 1 MB, o atraso pode ser de 1–2 s adicionais.
**Solução:**
1. Adicionar `fetchpriority="high"` e `loading="eager"` na tag ``
2. Injetar `` dinamicamente via `useEffect` assim que `backgroundImage` estiver disponível (ou via ``)
---
### 2.3 `useTheme` sendo chamado duas vezes para o mesmo dado
**Arquivos:** `HomePage.tsx` e `HomeScrollScene.tsx`
**Problema atual:**
```tsx
// HomePage.tsx
const { resolvedTheme } = useTheme()
const themedBackgroundImage = resolvedTheme === 'dark' ? ... : ...
// HomeScrollScene.tsx (recebe backgroundImage, mas chama useTheme DE NOVO)
const { resolvedTheme } = useTheme()
const isLight = resolvedTheme === 'light'
```
`resolvedTheme` é derivado duas vezes. Qualquer mudança de tema causa re-render em dois componentes separados com lógica duplicada. Além disso, `HomeScrollScene` não precisa conhecer o tema se receber `backgroundImage` já resolvida pelo pai — mas ainda usa `isLight` para estilos internos, o que é legítimo. O problema é a derivação `themedBackgroundImage` estar fora do componente que a consome.
**Solução:** Manter `isLight` em `HomeScrollScene` (necessário para estilos), mas mover `themedBackgroundImage` para dentro de `HomeScrollScene` eliminando a prop intermediária e a chamada dupla ao context em `HomePage`.
---
### 2.4 `AgentsCarousel`: `setInterval` sem cleanup confiável + CSS transform sem `will-change`
**Arquivo:** `AgentsCarousel.tsx`
**Problema atual:**
```tsx
const autoplayRef = useRef | null>(null)
// ...sem uso de requestAnimationFrame
// CSS translate via inline style, sem will-change: transform
```
- `setInterval` para animação de scroll não é sincronizado com o frame rate do browser → pode causar jank em displays 120 Hz
- Ausência de `will-change: transform` no track → o browser não promove a camada para GPU antes da primeira animação → primeiro frame pode ser janky
- Duplicação de slides (`[...agents, ...agents]`) sem `key` estável baseada em `agent.id` único (usa índice implicitamente)
---
### 2.5 `RiseCard`: IntersectionObserver por instância sem threshold otimizado
**Arquivo:** `HomeScrollScene.tsx`
**Problema atual:**
```tsx
// Cria 1 IntersectionObserver por card (até 6+ na home)
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setVisible(true)
observer.disconnect()
}
}, { threshold: 0.05 })
```
Cada `RiseCard` instancia seu próprio `IntersectionObserver`. Com 6 cards, são 6 observers ativos simultaneamente. O ideal é um único observer compartilhado (padrão singleton/context) que observa todos os elementos.
**Impacto:** Pequeno em volume baixo, mas escala mal. 6 observers × scroll events = trabalho desnecessário na main thread.
---
### 2.6 `
```
Isso insere uma tag `