Este guia diz o que construir, como e por quê. O protótipo mostra a tela; aqui está a razão de cada decisão, para que o dev resolva sozinho o que o protótipo não cobre. Quando houver conflito, vale: identidade v2.4 (skill identidade-ecomsmart) → este guia → protótipo.
1. Princípios de UX que governam tudo
- Um modelo mental para os cinco módulos. Todo módulo tem as mesmas cinco abas na mesma ordem (Dashboard, Configurar, Mensagens, Histórico, Assistente). O lojista aprende uma vez. Custo: um pouco de repetição de código; ganho: zero curva de aprendizado ao ativar o segundo módulo, que é exatamente o momento da venda.
- Duas portas para a mesma configuração. Formulário em cards numerados e conversa com o assistente escrevem no mesmo modelo (
ConfigModulo). O lojista que gosta de controle usa o formulário; o que tem pressa conversa. Nunca são dois sistemas: alterar num lado aparece no outro. - Nada é enviado sem confirmação explícita. O assistente executa leitura na hora (contar público, simular) e mostra a escrita como proposta num card; só o clique em "Confirmar" executa. É a regra que permite dar poder ao assistente sem medo.
- Módulo bloqueado é visível, não escondido. Aparece no menu com cadeado, abre a prévia desfocada com um argumento real da base. Esconder mata o upsell e gera a pergunta "onde está o RFV?".
- Estado em forma, não só em cor. Pílula, ponto, cadeado, borda esquerda. Cor semântica (verde, âmbar, vermelho) é reforço. Acessível e legível em tema escuro.
- O dado é o destaque. KPIs em Figtree 700 tabular; azul quando é dinheiro ou taxa de resultado. Nada mais é azul além de ações e dados.
- Mobile é primeira classe, não adaptação. Barra inferior fixa, uma decisão por tela, tabelas viram cards, assistente em folha inferior, abas roláveis. Layouts são desenhados para 390 px e crescem, não o contrário.
- Backend é a fonte de verdade de gating, mensagens e limiares. Guards e textos no front só melhoram UX. Se o backend diz
alerta: true, a tela mostra alerta; ela não recompara números.
2. Arquitetura de navegação
Três áreas, três layouts, três bundles lazy:
| Área | Layout | Rotas | Quem vê | |||||
|---|---|---|---|---|---|---|---|---|
| Público | public-layout (header marketing + rodapé em bloco) | /lp/:slug, /cadastro, /login, /precos | anônimo | |||||
| Onboarding | onboarding-layout (barra de passos, sem menu, fundo Névoa) | /onboarding/:passo (empresa, modulos, pagamento, whatsapp, loja, pronto) | logado, Empresa.onboarding.concluido = false | |||||
| App | app-shell (sidebar navy no web · barra inferior no mobile) | /app, /app/modulos, /app/m/:modulo/:aba, /app/m/:modulo/ativar, /app/assistente, `/app/conta/(assinatura | mcp | configuracoes), /app/base/(clientes | pedidos | produtos | rfv)` | logado |
Regras:
- A aba é rota.
/app/m/carrinho/configurarrecarrega na aba certa, é compartilhável e aparece no histórico do navegador. Estado interno de aba (signal solto) é proibido. moduleGuard(key)não redireciona. Resolvebloqueado: trueviaroute.datae omodulo-shellrenderiza a prévia com paywall. O guard atual (redirect + toast) sai.- Breadcrumb no web (
Início › Módulos › Carrinho), botão "‹ Módulos" no header do mobile. - Barra inferior mobile: Início (
/app), Módulos (/app/modulos), Assistente (/app/assistente), Conta (/app/conta/assinatura). Dentro de um módulo, o item Módulos fica ativo. - Voltar do assistente por módulo leva ao Dashboard do módulo, não ao Início.
- Query params guardam filtros de Histórico e Mensagens (período, status), para o link colado abrir igual.
3. Shell do app
Web: sidebar 232 px, navy #0B1033, item ativo com 12 % de branco, seções Meus módulos (5 itens com ponto colorido; bloqueado com opacidade 55 % e cadeado à direita; trial com etiqueta âmbar), Minha base, Conta. Header branco com nome da empresa, pílula de canal (WhatsApp Oficial · conectado, verde só aqui), medidor de mensagens do ciclo (3.240 / 10.000 + barra), etiqueta de trial e avatar.
Mobile: header de 52 px (logo ou "‹ Módulo"), conteúdo, barra inferior de 4 itens com ícone em linha 22 px e rótulo 10,5 px. O medidor de mensagens fica no header em texto pequeno.
Assistente: no web, painel fixo de 360 px à direita em toda tela de módulo (não é modal, não sobrepõe); no mobile, botão "Abrir assistente" no card e tela própria (aba Assistente). Mesmo componente <hub-assistente> nos dois.
Tema: claro por padrão, escuro por escolha (data-theme), tokens da identidade. Toda tela é testada nos dois.
4. O padrão de módulo (modulo-shell)
Componente único que recebe ModuloDef e renderiza cabeçalho + abas + <router-outlet> da aba. As abas são componentes por módulo que implementam uma interface comum.
| Aba | Propósito | Conteúdo fixo | Por quê |
|---|---|---|---|
| Dashboard | responder "está funcionando e quanto rende?" em 5 segundos | 4 KPIs · card "Configuração atual" (4 linhas + Editar) · funil de 4 etapas · gráfico mensal monocromático · painel do assistente (web) | KPI primeiro porque é a promessa do produto; a configuração resumida evita ir à aba Configurar só para conferir |
| Configurar | alterar com controle e revisão | cards numerados na ordem: Nome → Canal → Mensagem → Regra → Agendamento → Revisão (módulos sem campanha adaptam, ver §6) · faixa "Prefere conversar?" no topo · prévia e impacto à direita | cards numerados dão sensação de progresso e evitam formulário infinito; a Revisão com variáveis do template evita disparo com {{2}} sem fonte |
| Mensagens | gerir templates e qualidade do canal | rating do número no topo · tabela (nome, categoria Meta, status, "usar em", nota) · variáveis · classificação · erros recentes | rating do número é o que antecede queda de entrega; nota do template quase sempre UNKNOWN e não é alarme |
| Histórico | auditar e provar receita | chips de filtro · alerta de saúde (15 dias) · lista/tabela (quando, quem, o quê, status, resultado) · detalhe por linha | receita atribuída por vínculo ou janela é o argumento de renovação; o detalhe com payload e código da Meta é o que suporte precisa |
| Assistente ✦ | criar e alterar conversando | chat com passos · opções prontas · cards de leitura · prévia WhatsApp · card de confirmação · resumo em construção (web) | é o diferencial do produto e o caminho mais curto para o lojista sem tempo |
Cabeçalho do módulo: breadcrumb, ícone com cor do módulo (único lugar de cor de módulo além do ponto do menu), nome, uma linha de descrição (web), pílula de status (Ativo, Trial, Pausado, Aguardando canal), botão "✦ Configurar conversando". Banner de trial acima quando aplicável.
5. Estrutura conversacional (assistente)
5.1 Contrato de eventos (SSE) POST /api/assistente/conversar/
| Evento | Payload | Renderização |
|---|---|---|
texto | { html } | balão do assistente (permite <b>) |
opcoes | { itens: [{label, valor, recomendada?}] } | chips; a recomendada vem com borda azul; clique envia valor como mensagem do usuário |
tool_leitura | { nome, args, resultado } | card com borda esquerda verde: nome da tool em 600 e resultado em uma linha |
previa_whatsapp | { texto, botoes? } | balão estilo WhatsApp (fundo #0B141A, bolha #202C33) |
proposta_escrita | { id, titulo, resumo: [[chave, valor]], acoes: [{tool, args}] } | card com borda azul, lista chave/valor, botões "Confirmar" e "Editar algo", nota "Nada é enviado sem este clique." |
resumo | { itens: [[chave, valor, ok]] } | atualiza o painel "Resumo em construção" |
erro | { mensagem } | balão com borda esquerda vermelha e botão "Tentar de novo" |
POST /api/assistente/confirmar/:id executa acoes em transação e devolve tool_escrita (renderiza o card verde com "✓ executado"). "Editar algo" envia a mensagem "quero alterar X" e o backend reabre o slot.
5.2 Regras de interface
- Barra de passos no topo do chat (
passos[]vem do backend por módulo) mostra onde a conversa está. - Texto livre sempre permitido; opções são atalho, não restrição.
- Rascunho salvo por usuário e módulo (
ConversaAssistente); voltar à aba retoma de onde parou, com botão "Recomeçar". - "Ver como formulário" leva à aba Configurar com o
ConfigModuloparcial carregado e os cards já preenchidos marcados. - Toda mensagem do assistente que cita número traz a fonte (matriz de tal data, canal tal). O front não inventa números.
- Altura do chat: preenche a viewport menos o cabeçalho; input fixo embaixo; rolagem só na lista de mensagens.
- Mobile: o resumo em construção vira
<details>recolhido acima do chat, com contagem3/5.
5.3 Slots por módulo (o que a conversa precisa fechar)
| Módulo | Passos | Slots obrigatórios | Tools de leitura | Tools de escrita (na confirmação) |
|---|---|---|---|---|
| Carrinho | Origem · Canal · Régua · Regras · Confirmar | origem, canal, n_mensagens, delays[], templates[], cupom?, regras (valor mínimo, dias, frequência) | carrinho.simular_regua, canais.status, templates.listar | carrinho.atualizar_regua, cupons.criar, carrinho.ativar |
| Disparo RFV | Objetivo · Público · Mensagem · Agendamento · Confirmar | familia (reativacao/sazonal/novidade/informativo), segmentos[], modo_template, templates{}, quando | rfv.resumo, rfv.contar_publico, templates.listar, campanhas.estimar_custo | campanhas.criar_*, campanhas.agendar |
| Retenção | Boas-vindas · Aniversário · Regras · Confirmar | bv.delay, bv.horario, bv.template, bv.agrupador, aniv.horario, aniv.beneficio, aniv.template | retencao.previa_dia, templates.listar | retencao.boas_vindas.configurar/ativar, retencao.aniversario.configurar/ativar |
| E-commerceFlow | Catálogo · IA · Flows · Teste · Publicar | estoque_min, colecoes?, tom, proibicoes[], pagamentos[], horario_humano | catalogo.status, flow.simular_conversa | flow.regras.atualizar, prompts.nova_versao, flow.publicar |
| Campanhas Inteligentes | Diagnóstico · Objetivos · Cupons · Aprovação · Confirmar | objetivos[], cupom (valor, mínimo, validade), modo_aprovacao | campanhas.analisar_estoque, campanhas.sugerir_ofertas, campanhas.simular_margem | campanhas.aprovar_objetivo, cupons.regras, campanhas.ativar_objetivos |
Gates que a conversa respeita e explica: sem RFV calculado (Disparo, Retenção, Campanhas) o assistente diz o motivo exato do backend e oferece "me avise quando estiver pronto"; sem canal conectado, oferece o Embedded Signup; cota perto do limite, avisa antes de agendar.
6. Cada módulo em detalhe
6.1 Recuperação de Carrinho (carrinho)
Objetivo do usuário: "não perder venda que já estava quase fechada". Ele quer ver carrinhos chegando e dinheiro voltando.
- Dashboard: KPIs Carrinhos capturados · Recuperados · Receita confirmada (azul) · ROI (azul). Card de configuração mostra Origens, Canal, Régua, Regra. Funil Enviadas → Entregues → Lidas → Convertidas. Gráfico "Mensagens por dia". Mostrar "Saúde das origens" (webhook recebendo ou só coletando) como pílula no card de configuração: estado
coletando(webhook chega mas envio não configurado) tem que ficar visível, senão parece bug. - Configurar (por integração, não por empresa): 1 Origens (lista de integrações com webhook/sync e status), 2 Canal, 3 Régua (1 a 3 mensagens: delay, template, cupom), 4 Regra de envio (valor mínimo, dias da semana, frequência por cliente), 5 Revisão. Sem card "Nome" porque é automação contínua. Delay mínimo 30 min (backend). Sem gate de RFV (decisão de produto: público do carrinho está fora da matriz).
- Mensagens: templates
carrinho_*; variáveis{{1}}nome,{{2}}cupom,{{3}}link do carrinho. - Histórico: por carrinho (cliente, etapa da régua, status, receita recuperada por vínculo com pedido). Aba secundária "Webhooks recebidos" com payload cru sob demanda (só carrega ao abrir a linha: 3 KB por evento).
- Assistente: ver §5.3. Cupom criado na loja via integração.
- Reaproveitar:
features/comunicacoes/recuperacao-carrinho/(casca +configuracao-carrinho),recuperacao-cancelados/como sub-aba "Cancelados" do Histórico e da Configuração (mesma família),comm-webhooks-recebidos,comm-alerta-erro-envios. - Aceite: régua salva e ativa em ≤ 5 cliques a partir do Dashboard; carrinho de teste aparece em ≤ 60 s; estado
coletandovisível; mobile completo.
6.2 Disparo para Base RFV (disparo)
Objetivo: "mandar a mensagem certa para o grupo certo sem queimar meu número".
- Dashboard: KPIs Clientes segmentados · Enviadas (30 d) · Conversão (azul) · Receita gerada (azul). Card "Segmentação RFV" com data da matriz e link para a aba RFV. Lista das últimas campanhas com status.
- Sub-navegação interna (segunda linha de chips, não abas): Campanhas (reativação, sazonal, novidades, giftback, informativo, manual) · RFV (a
analise-rfvatual, com matriz e desempenho por segmento). Por quê chips e não abas: manter as cinco abas iguais em todos os módulos; a família da campanha é um filtro dentro de Campanhas. - Configurar (criar campanha): 1 Nome, 2 Canal, 3 Mensagem (modo único ou por segmento,
comm-mensagem-segmentada), 4 Público (cards de segmento com contagem de contactáveis, slider de limite), 5 Agendamento (data, cadência fixa por tipo de canal, previsãocomm-resumo-disparono rodapé do card), 6 Revisão. Gate de RFV: sem matriz, esconde o formulário e mostraui-rfm-gatecom a mesma mensagem do backend. - Mensagens: templates por família; classificação "usar em" (reativação, sazonal, informativo…). Informativo não mostra dinheiro em nenhum lugar.
- Histórico: por campanha (família, envios, segmentos, status, receita e ROI; informativo mostra "sem receita"). Filtro por família e período.
- Assistente: cria a campanha em 4 perguntas; sempre informa contactáveis, custo e duração antes de pedir confirmação.
- Reaproveitar:
CampanhaOneShotState,TemplatePorSegmentoState,comm-rfm-segmento-cards,comm-mensagem-segmentada,comm-resumo-disparo,comm-desempenho-segmentos-familia, telasreativacao/,sazonais/,informativos/,novidades/,giftback/,analise-rfv/. - Aceite: criar e agendar campanha em ≤ 3 min; gate de RFV com motivo; custo e duração visíveis antes de agendar; uma campanha só pode ser agendada se todos os segmentos escolhidos têm template.
6.3 Retenção (retencao)
Objetivo: "ligar uma vez e esquecer, sabendo que está rodando".
- Dashboard: KPIs Boas-vindas enviadas · Aniversários enviados · Convertidos · Receita gerada (azul). Dois cards lado a lado, um por automação, com toggle Ligada/Desligada, próximo disparo e KPIs próprios. Prévia do dia: "amanhã 12 aniversariantes segmentados".
- Configurar: 1 Canal (é o primeiro porque as duas automações compartilham), 2 Boas-vindas (delay, horário, template, agrupador de canais), 3 Aniversariantes (horário, benefício, template), 4 Regra de envio (informativa: sem enriquecido, anti-duplicação, só segmentados), 5 Revisão. Toggle de ativação exige RFV; desligar e editar nunca exigem.
- Mensagens:
boas_vindas_*,aniversario_*. - Histórico: por dia e automação (envios, convertidos, receita), com a saúde dos envios acima da lista.
- Assistente: dois blocos de perguntas; sempre mostra a prévia do dia seguinte antes de confirmar.
- Reaproveitar:
aniversariantes/,boas-vindas/,RetencaoAutomacaoState,comm-funil-envios,chartEnviosMensaisOptions. - Aceite: ligar as duas automações em ≤ 2 min; toggle bloqueado com motivo quando sem RFV; prévia do dia correta.
6.4 E-commerceFlow (flow)
Objetivo: "vender dentro do WhatsApp sem atendente".
- Dashboard: KPIs Conversas com IA · Flows abertos · Pedidos no WhatsApp · Ticket médio (azul). Card "Funil do Flow" (conversa → flow aberto → pedido). Lista de conversas recentes com desfecho.
- Sub-navegação interna (chips): Catálogo (produtos sincronizados, elegíveis, fotos faltando) · IA vendedora (os 5 nós com versão, editor de prompt com diff e "testar") · Flows (telas do Flow JSON, publicar, testar em número de teste) · Conversas (o bate-papo atual filtrado pelo canal do Flow, com etiqueta "IA" ou "humano").
- Configurar: 1 Catálogo (regras de elegibilidade), 2 Canal (precisa Flows habilitado; se não, instrução), 3 IA vendedora (tom, proibições, versão ativa por nó), 4 Flows (pagamentos aceitos, frete, campos), 5 Atendimento humano (horário, fila), 6 Revisão.
- Mensagens: templates de abertura e pós-compra (
UTILITY), lembrete de Pix. - Histórico: por conversa (cliente, caminho percorrido, desfecho, pedido, valor). Detalhe abre a transcrição.
- Assistente: configura regras e prompts e permite simular a conversa como cliente dentro do chat (tool
flow.simular_conversa), que é o teste de aceitação natural. - Reaproveitar:
agentes-ia/(editor de prompts e versões),comunicacoes/conversas/,ecommerce/produtos. - Aceite: publicar Flow e fechar pedido de teste em ≤ 10 min; simulação funciona na aba Assistente; catálogo mostra o que está fora e por quê.
6.5 Campanhas Inteligentes (campanhas)
Objetivo: "que o sistema me diga o que ofertar e eu só aprove".
- Dashboard: KPIs Objetivos ativos · Clientes elegíveis · Ofertas aprovadas hoje · Margem preservada (azul). Fila do dia: "3 sugestões aguardando aprovação" com botão único. Gráfico de pedidos por objetivo.
- Sub-navegação interna (chips): Objetivos (O1 a O14, cada um com toggle, elegíveis hoje, tier, descrição de uma linha) · Aprovações (fila diária: cliente, objetivo, produto sugerido, cupom, aprovar/rejeitar em lote) · Cupons (regras por faixa).
- Configurar: 1 Objetivos ativos, 2 Regras de cupom (faixas, mínimo, validade, frequência por cliente), 3 Canal, 4 Aprovação (manual ou automática até um teto), 5 Revisão.
- Mensagens: um template por objetivo, com variáveis de produto e cupom.
- Histórico: por sugestão diária (objetivo, clientes, cupom, decisão, pedidos e receita).
- Assistente: começa por diagnóstico (estoque, afinidade, VIPs) e conduz à escolha de objetivos; simula margem antes de confirmar.
- Reaproveitar: tela "Ofertas sugeridas" e a lógica de objetivos da Gestão (a portar para o Hub),
giftback/para faixas de cupom,novidades/para o painel BI de produto. - Aceite: aprovar a fila do dia em 1 clique; toda sugestão mostra margem estimada; rejeição pede motivo em um chip (preço, público, produto) para alimentar o motor.
7. Telas fora dos módulos (resumo; detalhes na spec de 11/09)
- Landing por módulo: ordem fixa nav → hero → banner Profundo → título/parágrafo → benefícios → bloco de 3 dados → preço → assistente → outros módulos → FAQ → rodapé. Pré-render estático, schema FAQPage e Product.
- Cadastro: CNPJ primeiro, autocomplete com debounce 300 ms e mínimo 8 dígitos, depois nome, WhatsApp, e-mail, senha ou Google.
- Onboarding: 6 passos, retomável, provisionamento em paralelo com a conexão do WhatsApp, polling de status.
- Início: KPIs consolidados, 5 cards de módulo (ativo com 2 KPIs; bloqueado com argumento e "Testar grátis"), sugestão do assistente com base real.
- Módulos (lista): estado e chips das 5 abas.
- Bloqueado / Ativar: prévia com KPIs de exemplo e overlay; checkout adiciona item Stripe e oferece os outros módulos.
- Assinatura & uso: cota por módulo, custo Meta repassado, faturas, portal Stripe.
- Conectar Claude / GPT: URL do MCP, token com escopos, instruções por cliente, atividade recente.
8. Inventário de componentes
Existentes em shared/ a manter: ui-button, ui-input, ui-select, ui-modal, ui-table, responsive-table, bottom-sheet, ui-tabs, ui-toast, stat-card, date-range-picker, paginator, empty-state, skeleton, funil, rfm-matriz, rfm-gate, ui-canal-status-badge, ui-template-vars-resumo, ui-checkbox-dropdown, comm-* de comunicações.
Novos: modulo-shell (cabeçalho + abas + outlet), modulo-kpis (4 KPIs com regra do azul), modulo-config-cards (cards numerados genéricos), hub-assistente (chat SSE com os 7 eventos), hub-assistente-resumo, ui-quota-bar, ui-trial-banner, ui-locked-inline, ui-locked-preview (overlay de paywall), ui-confirm-dialog (com número de afetados), ui-breadcrumb, mobile-tabbar, ui-chip-filter (com query params), wa-preview (bolha WhatsApp).
Tokens: substituir em src/tailwind.input.css conforme identidade v2.4 (Figtree, #0A5BF0, #0B1033, #F6F8FC, tema escuro azul-noite) e remover Inter.
9. Estados, acessibilidade e desempenho
- Todo componente de dados tem os estados: carregando (skeleton), vazio (ícone, título, texto, ação), erro (o que houve, o que fazer, tentar de novo), sem permissão (bloqueado inline). KPI em carregamento mostra "—".
- Confirmação obrigatória em: cancelar campanha, desligar automação, apagar template, cancelar módulo, publicar Flow. Sempre com o número de pessoas afetadas.
- Foco visível em tudo; chips e abas navegáveis por teclado;
aria-livepara toasts; contraste AA conferido nos dois temas; alvo de toque ≥ 44 px no mobile. - Números:
Intl.NumberFormat('pt-BR'),tabular-numsem colunas, ROI nulo é "—". - Desempenho: lazy por área e por módulo; listas de histórico paginadas no backend; payload de webhook só ao abrir; SSE do assistente com reconexão; imagens de landing em
webp.
10. Definição de pronto por tela
Uma tela só está pronta quando: funciona nos dois temas e nos dois tamanhos; tem os 4 estados; usa só tokens da identidade; tem rota própria e deep link; passa no checklist da skill identidade-ecomsmart; tem spec com pelo menos o cenário feliz e o de erro; e os textos passam no "diga / não diga" (sem "ilimitado", sem "chatbot", CTA com verbo).
11. Ordem de implementação sugerida
- Tokens +
app-shellnovo (sidebar, header, mobile tabbar, tema) emodulo-shellcom abas por rota. - Módulo Carrinho completo (5 abas) migrando as telas existentes. Serve de referência para os outros.
hub-assistentecom os 7 eventos e o wizard do Carrinho.- Retenção e Disparo RFV (migração das telas existentes para as abas).
- Público + onboarding + billing (dependem de Stripe e CNPJ no backend).
- Campanhas Inteligentes e E-commerceFlow (dependem de backend novo).