# Como Corrigir IA Colocando Código de Servidor em Componentes do Cliente

> Agentes de IA vazam consultas de banco de dados, variáveis de ambiente secretas e APIs Node.js para componentes 'use client', expondo lógica exclusiva do servidor ao bundle do navegador.

**Type:** Failure  
**Tools:** Cursor, Claude Code, Codex, Windsurf  
**Stack:** Next.js, TypeScript  
**Updated:** 2026-06-08

---

O agente adiciona uma diretiva `"use client"` a um componente que importa Prisma, `fs` ou uma variável de ambiente secreta — o que envia esse código para o bundle do navegador de cada visitante.

## O sintoma

Um componente marcado como `"use client"` faz uma chamada direta ao banco de dados ou lê um segredo `process.env`.

```tsx
"use client";
import { db } from "@/lib/db"; // Prisma client — Node.js only
import { useState, useEffect } from "react";

export function UserCard({ id }: { id: string }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // db is a Node.js module — this will throw at runtime in the browser
    db.user.findUnique({ where: { id } }).then(setUser);
  }, [id]);

  return <div>{user?.name}</div>;
}
```

A compilação pode ser bem-sucedida (Next.js agrupa a importação), mas a página lança um erro em tempo de execução no navegador porque `@prisma/client` requer APIs Node.js.

## Por que isso acontece

O agente vê que os dados são necessários dentro de um componente que também usa estado ou efeitos, e recorre à camada de dados que conhece. Ele não modela a fronteira servidor/cliente nem sabe que componentes `"use client"` não podem importar módulos exclusivos do Node.js.

## Como identificar

- `"use client"` no topo de um arquivo que também importa de `@/lib/db`, `prisma`, `fs`, `path` ou `crypto`.
- `process.env.DATABASE_URL` ou qualquer variável `_SECRET_` lida dentro de um arquivo `"use client"`.
- A saída de compilação contém `Critical dependency: the request of a dependency is an expression` ou um aviso de bundle do Prisma.
- O pacote `server-only` está ausente do projeto.

## Como corrigir

Divida em um componente de servidor pai que busca os dados e um componente de cliente filho que lida com a interatividade.

```tsx
// app/users/[id]/page.tsx — Server Component (no directive)
import { db } from "@/lib/db";
import { UserCard } from "./UserCard";

export default async function UserPage({ params }: { params: { id: string } }) {
  const user = await db.user.findUniqueOrThrow({ where: { id: params.id } });
  // Serialize — pass plain data, not the Prisma object
  return <UserCard name={user.name} email={user.email} />;
}
```

```tsx
// app/users/[id]/UserCard.tsx — Client Component
"use client";
import { useState } from "react";

export function UserCard({ name, email }: { name: string; email: string }) {
  const [expanded, setExpanded] = useState(false);
  return (
    <div>
      <p>{name}</p>
      {expanded && <p>{email}</p>}
      <button onClick={() => setExpanded((v) => !v)}>Toggle</button>
    </div>
  );
}
```

```txt
[ ] Install "server-only" and import it at the top of every server-side lib file
[ ] No db/prisma imports in "use client" files
[ ] No process.env secrets read in "use client" files
[ ] Server Component fetches data; Client Component receives plain props
[ ] Use Server Actions (not useEffect+fetch) when a client interaction needs db access
```

## Prompt de correção

```txt title="Fix Prompt"
This "use client" component imports server-only modules (Prisma, fs, or secret
env vars). Refactor it: move all data fetching into an async Server Component
parent, pass only serializable props to the client component, and keep "use
client" only on the part that needs browser APIs or React state. Add
"server-only" to any shared lib files that must never reach the browser.
```

## Teste

```bash
# List all "use client" files that also import known server-only packages
grep -rl '"use client"' app/ | xargs grep -l "prisma\|@/lib/db\|\"fs\"\|\"path\"\|\"crypto\"" && echo "FAIL: server code in client component" || echo "OK"
```