Todo projeto chega num ponto em que ninguém mais consegue explicar de cabeça como as peças se conectam. Quais containers rodam na VPS, o que fala com o quê, como as tabelas se relacionam. A documentação existe na cabeça de quem escreveu o código — e some quando essa pessoa esquece.

Mermaid resolve a parte chata desse problema: você escreve texto, ele vira diagrama. Sem arrastar caixinha, sem .drawio ilegível no diff do git. E como é texto, é exatamente o tipo de coisa que o Claude gera bem — inclusive lendo seu projeto real e produzindo o diagrama sozinho, sem você descrever nada.

Por que Mermaid e não Draw.io ou Figma

Três motivos práticos. Primeiro, versiona: o diagrama é um bloco de texto dentro de um .md, então ele entra no mesmo PR que mudou a arquitetura. Segundo, renderiza nativo: GitHub, Notion e Obsidian mostram o diagrama sem plugin. Terceiro — e o mais relevante aqui — é o formato mais fácil de gerar e editar via IA, porque é sintaxe estruturada, não XML verboso nem coordenadas de canvas.

A desvantagem é o controle visual fino: se você precisa de um layout pixel-perfect pra apresentação executiva, Mermaid não é a ferramenta. Pra documentação técnica que o time vai manter, é a escolha certa.

Os tipos de diagrama que cobrem quase todo projeto

C4 Model — visão em camadas da arquitetura lógica. Nível de Contexto mostra quem usa o sistema e com que serviços externos ele conversa:

C4Context
    title Contexto do Sistema - FitFlow

    Person(usuario, "Usuário", "Pessoa que treina e registra treinos")
    System(fitflow, "FitFlow", "App de tracking de treinos")
    System_Ext(whatsapp, "WhatsApp", "Notificações e lembretes")
    System_Ext(auth, "Auth Provider", "Autenticação OAuth")

    Rel(usuario, fitflow, "Registra treinos, consulta progresso")
    Rel(fitflow, whatsapp, "Envia lembretes via API")
    Rel(fitflow, auth, "Autentica usuário")

Nível de Container detalha as caixas internas — frontend, backend, banco:

C4Container
    title Container - FitFlow

    Person(usuario, "Usuário")

    Container_Boundary(fitflow, "FitFlow") {
        Container(web, "Web App", "Next.js", "Interface do usuário")
        Container(api, "API", "NestJS", "Regras de negócio")
        ContainerDb(db, "Banco de Dados", "PostgreSQL", "Treinos e usuários")
    }

    Rel(usuario, web, "Usa", "HTTPS")
    Rel(web, api, "Chama", "REST/JSON")
    Rel(api, db, "Lê/escreve", "Prisma")

ERD — modelagem de banco, direto de um schema.prisma se você já tiver um:

erDiagram
    USUARIO ||--o{ TREINO : "registra"
    TREINO ||--|{ EXERCICIO : "contém"
    USUARIO {
        string id PK
        string email
        string nome
    }
    TREINO {
        string id PK
        string usuario_id FK
        string nome
        datetime data
    }

Arquitetura de infra — onde as coisas rodam de verdade: VPS, Docker, Traefik, banco central:

flowchart TD
    Internet(["Internet"]) -->|HTTPS :443| Traefik

    subgraph VPS["VPS Hostinger"]
        Traefik["Traefik (reverse proxy + SSL)"]
        subgraph Docker["Docker"]
            App["fitflow.nico.dev.br"]
            Postgres[("PostgreSQL")]
        end
        Traefik -->|"fitflow.nico.dev.br"| App
        App --> Postgres
    end

Sequence diagram — ordem temporal de chamadas, ideal pra auth flow ou lifecycle de request:

sequenceDiagram
    actor Usuario
    participant Web as Web App
    participant API
    participant DB

    Usuario->>Web: Preenche login
    Web->>API: POST /auth/login
    API->>DB: Busca usuário
    DB-->>API: Retorna dados
    API-->>Web: 200 { token }

Regra prática pra escolher: se a pergunta é “quem conversa com quem, sem ordem definida”, é C4 ou infra. Se é “em que ordem as coisas acontecem”, é sequence. Se é “como os dados se relacionam”, é ERD.

Gerando do zero: os prompts

O Claude já sabe gerar Mermaid direto, mas prompts específicos economizam idas e vindas:

“Cria um diagrama C4 de contexto pro projeto X: é um app de [descrição], usuários fazem [ação principal], integra com [serviços externos].”

“Modela o banco em ERD: tenho as tabelas usuário, pedido e produto, um usuário faz vários pedidos, um pedido tem vários produtos.”

“Desenha a infra: VPS com Traefik, três containers Docker (nomeia os domínios), Postgres central que todos usam.”

“Faz um sequence diagram do fluxo de login: frontend chama a API, API valida no provider OAuth, busca o usuário no banco, retorna token.”

Quanto mais concreto o input — nomes reais de domínio, de tabela, de serviço — mais o diagrama vira documentação de verdade em vez de ilustração genérica.

O caso que mais economiza tempo: modo retroativo

A parte mais útil na prática não é gerar diagrama do zero — é apontar pro projeto que já existe, sem README atualizado, e pedir pro Claude extrair a arquitetura sozinho:

“Documenta esse projeto visualmente: olha o docker-compose, o schema.prisma e a estrutura de pastas, e gera os diagramas de infra, ERD e C4 container.”

Nesse modo o Claude escaneia arquivos estruturados — docker-compose.yml e labels do Traefik viram infra, schema.prisma vira ERD, package.json mais a estrutura de pastas vira C4 Container. São fontes confiáveis porque já são texto estruturado, não interpretação de lógica solta.

O ponto de atenção: o que vem direto de config é fato, mas relação de negócio inferida de nome de variável ou de código espalhado é suposição. Um bom resultado retroativo avisa o que foi extraído com certeza e o que precisa da sua confirmação — se o diagrama vier sem essa distinção, vale perguntar antes de tratar como documentação oficial.

Organizando a documentação

Diagrama solto na conversa não vira documentação — precisa de lugar fixo. Convenção que funciona bem: docs/diagrams/ na raiz do repo, um arquivo .md por diagrama, nome no padrão tipo-nome-do-projeto.md (infra-fitflow.md, erd-fitflow.md).

Pra sistemas com várias partes, prefira vários diagramas pequenos a um gigante ilegível — um C4 Contexto geral mais um Container por serviço, em vez de tentar enfiar tudo numa imagem só. E pra quem tem múltiplos projetos na mesma VPS, funciona bem separar um diagrama de infra “guarda-chuva” (todos os containers) dos diagramas de arquitetura lógica de cada projeto individual.

O detalhe que decide se isso vira hábito ou vira lixo desatualizado: re-rodar o scan quando a infra muda, não só na primeira vez. Diagrama desatualizado é pior que não ter diagrama nenhum, porque ele mente com confiança. Se sua rotina já tem CLAUDE.md e comandos customizados, vale criar um /diagram-infra que roda esse fluxo de scan sempre que precisar, em vez de reexplicar o contexto toda vez.