Rythmiq — Especificação de Produto
Documento vivo. Cobre visão, personas, funcionalidades, fluxos, telas, UX/UI, arquitetura, stack, banco de dados, APIs, segurança, testes, estrutura de projeto, roadmap, critérios de aceitação e riscos. Serve como referência para qualquer desenvolvedor assumir o projeto.
1. Entendimento do projeto
Rythmiq é uma plataforma SaaS multi-tenant para gestão de centros de treinamento de Ginástica Rítmica (GR), com foco no acompanhamento da performance de atletas em treinos e competições. O sistema mantém um catálogo de movimentos de GR (com imagem, símbolo e nota de dificuldade), permite montar a série de cada atleta a partir desse catálogo, registrar em cada treino se cada movimento da série foi executado (mais observações gerais), e visualizar a evolução da atleta ao longo do tempo em gráficos e tabelas. Pode ser usada por centros de treinamento, academias e professores autônomos. Hoje não existe ferramenta equivalente no mercado brasileiro — esse é o principal diferencial e também o principal risco (não há benchmark de UX para copiar; validação com usuários reais é essencial).
2. Perguntas críticas (respondidas)
Três decisões de arquitetura foram levantadas por bloquearem escolhas técnicas relevantes e já foram respondidas:
| # | Pergunta | Decisão |
|---|---|---|
| 1 | Alcance de plataforma (app nativo x web)? | Web responsivo, instalável como PWA. Sem apps nativos por ora. |
| 2 | Como matriz/filial se relacionam nos dados? | Tenants separados, agrupados por um TenantGroup opcional. |
| 3 | Como modelar movimento e nota de dificuldade? | Seguir o Código de Pontuação da FIG (aparelho + grupo de dificuldade + valor em incrementos de 0,10). |
3. Premissas adotadas
Decisões tomadas por boa prática de mercado, não especificadas explicitamente pelo usuário:
- Planos (FREE / INDIVIDUAL / CENTRO_DE_TREINAMENTO) existem como atributo cadastral do tenant desde o MVP, mas sem gating de features/limites — o usuário sinalizou que as características de cada plano serão especificadas depois. Cobrança fica para a Fase 7 (Evolução).
- Menores de idade: perfil RESPONSÁVEL existe desde o MVP; cadastro de atleta menor exige um responsável vinculado e captura de consentimento (LGPD) no momento do cadastro.
- Mercado/idioma: pt-BR, timezone
America/Sao_Paulo, moeda BRL (para quando a cobrança existir). - Multi-tenancy: reaproveita o padrão já validado em projetos anteriores — banco único, isolamento por coluna
tenantId, todo acesso a dado passa por um helper de escopo de tenant no servidor.TenantGroupé a única camada nova, para agrupar matriz + filiais. - Base técnica: continua o scaffold já criado (Next.js 15 + React 19 + TypeScript, Prisma + PostgreSQL, NextAuth com sessão JWT, Tailwind com a identidade visual do brand kit já aplicada).
- Competições: como o usuário citou acompanhamento "em treinamentos e em competições", o MVP inclui registro simplificado de competição e resultado (nota final e colocação por aparelho) — não o protocolo completo de julgamento da FIG (múltiplos jurados, painéis D/E/Penalidade), que fica para uma fase futura caso haja demanda.
- Cobrança, comunicação interna, financeiro de mensalidades e integração com WhatsApp ficam fora do MVP, conforme o próprio usuário sinalizou ("poderá evoluir para..."). Estão desenhados neste documento (seções 6 e 17) para não bloquear a arquitetura quando chegar a hora.
- Direitos de imagem da FIG: o Código de Pontuação e os símbolos oficiais de movimento são material protegido da FIG. O catálogo semeado no banco replica a estrutura (aparelho, grupo, valor), mas usa ilustrações/símbolos próprios do Rythmiq em vez de reproduzir os desenhos oficiais — evita risco de propriedade intelectual.
4. Visão geral da solução
O que é: um sistema de gestão e acompanhamento de evolução técnica de atletas de Ginástica Rítmica.
Para quem: centros de treinamento, academias de GR e professores autônomos no Brasil.
Problema que resolve: hoje o acompanhamento de série, execução de movimentos e evolução da atleta é feito em planilhas, cadernos ou na memória do professor — sem histórico estruturado, sem visão de evolução ao longo do tempo, sem padronização entre professores do mesmo centro.
Como funciona: o centro cadastra suas turmas e atletas; o catálogo de movimentos já vem pré-carregado segundo o Código de Pontuação da FIG; o professor monta a série de cada atleta escolhendo movimentos do catálogo; a cada treino, o professor abre a série da atleta e marca execução (sim/não) por movimento, mais observações; o sistema acumula esse histórico e apresenta gráficos/tabelas de evolução por movimento, por aparelho e por série ao longo do tempo, além do histórico de competições.
Diferencial: é o único sistema do mercado brasileiro pensado especificamente para o vocabulário técnico da Ginástica Rítmica (aparelhos, grupos de dificuldade, valores FIG) em vez de um CRM genérico de academia adaptado.
5. Personas
| Persona | Perfil | Objetivo na plataforma | Necessidades | Dificuldades hoje |
|---|---|---|---|---|
Gestora do centro (papel GESTOR) | Dona/diretora de um centro de treinamento, gerencia de 1 a várias turmas e professores | Ter visão consolidada do centro: quantas atletas, quantos professores, adimplência (futuro) | Cadastro simples de turmas/professores/atletas, visão gerencial rápida | Planilhas soltas por professor, sem padronização, sem histórico centralizado |
Professor(a)/treinador(a) (papel PROFESSOR) | Ministra os treinos, monta e ajusta as séries | Registrar rapidamente, durante ou logo após o treino, o que cada atleta executou | Registro rápido (poucos toques), no celular/tablet à beira do tapete | Anotar em caderno durante o treino é lento e se perde; comparar treino a treino é manual |
Atleta (papel ATLETA) | Pratica GR, pode ser menor ou maior de idade | Acompanhar a própria evolução e a série atual | Visão simples do que já executa bem e do que precisa treinar mais | Não tem visibilidade do próprio progresso, depende do que o professor lembra de falar |
Responsável (papel RESPONSAVEL) | Pai/mãe/tutor de atleta menor de idade | Acompanhar a evolução da filha/tutelada, sem se envolver na operação do treino | Visão de evolução e frequência, comunicação com o centro (futuro) | Só fica sabendo da evolução em conversas informais ou reuniões esporádicas |
Super Admin (papel SUPER_ADMIN) | Equipe Rythmiq, sem vínculo com nenhum tenant | Administrar a plataforma: cadastro de centros, planos, suporte | Visão de todos os tenants, ferramentas de suporte e auditoria | N/A (papel novo, interno da operação Rythmiq) |
6. Funcionalidades
Prioridade: 🔴 Crítica · 🟠 Alta · 🟡 Média · 🟢 Baixa
Esta seção foi atualizada para refletir o que está de fato construído e em uso, não apenas o planejamento inicial. A tabela "MVP" abaixo é o registro histórico de escopo; o estado real de cada módulo está na tabela de funcionalidades por perfil logo a seguir.
6.1 Funcionalidades por perfil (estado atual)
| Módulo | Super Admin | Gestor | Professor | Atleta | Responsável |
|---|---|---|---|---|---|
| Centros (tenants) | CRUD completo — nome, slug, CNPJ, tipo, grupo (matriz/filial), plano, status, contato, e-mail, endereço | — | — | — | — |
| Logs (auditoria) | Consulta a trilha de ações (filtro por centro/ação/entidade/módulo) | — | — | — | — |
| Módulos por perfil | Habilita/desabilita cada módulo por papel (GESTOR/PROFESSOR/ATLETA/RESPONSAVEL), um papel por vez, com ações granulares (visualizar/cadastrar/editar/deletar); toda alteração é auditada | — | — | — | — |
| Banco de dados (manutenção) | Apagar todos os dados de um centro (com confirmação e opção de forçar), recarregar o catálogo oficial de movimentos, backup (placeholder) | — | — | — | — |
| Usuários do centro | — | Convidar, editar, desativar (professor/atleta/responsável) | — | — | — |
| Meu perfil | Editar dados pessoais, foto, endereço e trocar senha | Editar dados pessoais, foto, endereço e trocar senha | Editar dados pessoais, foto, endereço e trocar senha | Editar dados pessoais, foto, endereço e trocar senha | Editar dados pessoais, foto, endereço e trocar senha |
| Turmas | — | CRUD, gestão de atletas da turma, dias/horários de aula (Segunda a Domingo, com hora de início e término por dia) | CRUD, gestão de atletas da turma, dias/horários de aula | — | — |
| Atletas | — | CRUD completo | CRUD completo | Consulta a própria ficha | Consulta a ficha da tutelada |
| Equipes | — | CRUD, gestão de membros (titular/reserva) | CRUD, gestão de membros (titular/reserva) | — | — |
| Responsáveis | — | Listagem e vínculo com atletas | Consulta | — | — |
| Lista de espera | — | CRUD, controle de status (pendente/avaliado/aceito/rejeitado) | CRUD, controle de status | — | — |
| Catálogo de movimentos (FIG) | Mantém o catálogo oficial (139 elementos de Saltos/Equilíbrio/Rotação extraídos do Código de Pontuação FIG 2025-2028, mais Flexibilidade/Onda e Dificuldade de Aparelho) | Consulta e cria movimento customizado do centro | Consulta e cria movimento customizado do centro | Consulta | Consulta |
| Séries | — | Monta e edita a série da atleta/equipe por aparelho | Monta e edita a série da atleta/equipe por aparelho | Consulta a própria | Consulta a da tutelada |
| Treinos | — | Registra e consulta o histórico | Registra e consulta o histórico | Consulta o próprio histórico e execução por movimento | Consulta o histórico da tutelada |
| Competições | — | Registra competição e resultado por atleta | Registra competição e resultado por atleta | Consulta | Consulta |
| Calendário (menu próprio) | — | CRUD de eventos (título, tipo, local, dia inteiro ou horário, período, descrição); visão em dia/semana/mês/agenda | CRUD de eventos | Consulta | Consulta |
| Comunicação → Mensagens | — | Envia, responde (com histórico de thread) e marca como lida automaticamente ao abrir | Envia, responde e marca como lida automaticamente ao abrir | — | — |
| Alertas | Dispara para toda a plataforma (todos os tenants), para TODOS os usuários ou só um papel; gerencia os próprios | Dispara para o próprio centro, para TODOS os usuários ou só um papel; gerencia os próprios | Recebe, vê em destaque no dashboard até fechar/ler, consulta histórico em "Recebidos" | Recebe, vê em destaque no dashboard até fechar/ler, consulta histórico em "Recebidos" | Recebe, vê em destaque no dashboard até fechar/ler, consulta histórico em "Recebidos" |
| Listagens (geral) | — | Busca, filtros, alternância lista/cards, paginação com linhas por página configurável | Idem | Idem, restrito aos próprios dados | Idem, restrito à tutelada |
MVP
| # | Funcionalidade | Usuário | Objetivo / fluxo resumido | Regras de negócio principais | Dependências | Prioridade |
|---|---|---|---|---|---|---|
| 1 | Autenticação (login, recuperar senha) | Todos | Login por e-mail/senha; fluxo de "esqueci minha senha" por e-mail | Rate limit de tentativas; sessão JWT; senha com requisitos mínimos | — | 🔴 |
| 2 | Onboarding do centro | Gestor (self-service) | Wizard: dados do centro → plano desejado → convite do primeiro professor | Cria Tenant em status TRIAL; e-mail do gestor vira o primeiro User com papel GESTOR | Auth | 🔴 |
| 3 | Cadastro de tenants (centros) | Super Admin | CRUD de centros: nome, CNPJ, tipo (matriz/filial/independente), TenantGroup, plano, status ativo/inativo | CNPJ único quando informado; filial deve referenciar uma matriz existente | — | 🔴 |
| 4 | Gestão de usuários do centro | Gestor | Convidar/editar/desativar professor, atleta, responsável | E-mail único na plataforma; só GESTOR gerencia usuários do próprio tenant | Onboarding | 🔴 |
| 5 | Catálogo de movimentos (FIG) | Super Admin (mantém catálogo oficial) / Professor-Gestor (cria movimentos customizados) | Listar/filtrar movimentos por aparelho e grupo de dificuldade; cadastrar movimento customizado do centro | Movimento oficial (oficial = true) não pode ser editado/excluído pelo tenant; valor de dificuldade em incrementos de 0,10 | — | 🔴 |
| 6 | Cadastro de turmas | Gestor/Professor | CRUD de turma: nome, professor responsável | Turma pertence a um único tenant | Usuários | 🔴 |
| 7 | Cadastro de atletas | Gestor/Professor | CRUD de atleta: dados pessoais, data de nascimento, turma; se menor, exige responsável vinculado + consentimento | Atleta menor sem responsável vinculado não pode ser salva | Turmas, Usuários | 🔴 |
| 8 | Montagem de série | Professor | Monta a série da atleta por aparelho, escolhendo e ordenando movimentos do catálogo | Valor de dificuldade total da série calculado automaticamente pela soma dos movimentos | Movimentos, Atletas | 🔴 |
| 9 | Registro de treino | Professor | Abre a série da atleta no dia do treino, marca executado/não executado por movimento, adiciona observação geral | Um registro de treino por atleta por data; não pode registrar execução de movimento fora da série vigente | Séries | 🔴 |
| 10 | Registro simplificado de competição | Professor/Gestor | Cadastra competição (nome, data, local) e resultado por atleta/aparelho (nota final, colocação) | Resultado sempre vinculado a uma atleta do próprio tenant | Atletas | 🔴 |
| 11 | Evolução da atleta | Professor/Gestor/Atleta/Responsável | Gráfico e tabela de execução ao longo do tempo, por movimento e por aparelho; linha do tempo de competições | Responsável e Atleta só veem os próprios dados | Treinos, Competições | 🔴 |
| 12 | Layout padrão responsivo | Todos | Sidebar com navegação, header com breadcrumb e menu de perfil, 320px→desktop | Sidebar colapsa em bottom-nav/drawer no mobile | — | 🔴 |
| 13 | Dashboard inicial por perfil | Todos | Indicadores relevantes ao papel (ex.: gestor vê nº de atletas/turmas; professor vê treinos da semana) | Cada card do dashboard respeita a mesma regra de visibilidade por papel | Demais módulos | 🟠 |
| 14 | Configurações de conta | Todos | Editar nome, trocar senha, ver dados do próprio tenant (não editável por não-gestor) | — | Auth | 🟠 |
V2
| # | Funcionalidade | Objetivo | Prioridade | Status |
|---|---|---|---|---|
| 1 | Cobrança de planos (assinatura) | Ativar plano pago com cartão/boleto (ex.: via Stripe) | 🟠 | Não iniciado |
| 2 | Gestão financeira simples de mensalidades | Registrar mensalidade da atleta, status pago/pendente, vencimento | 🟡 | Não iniciado |
| 3 | Mensagens entre gestor/professor/atleta/responsável dentro da plataforma | 🟡 | ✅ Construído — módulo Mensagens (enviadas/recebidas, resposta com thread, leitura automática) | |
| 4 | Exportação de relatórios | PDF/Excel da evolução da atleta para reuniões e federações | 🟡 | Não iniciado |
| 5 | Log de ações sensíveis visível ao Super Admin | 🟠 | ✅ Construído — tela de Logs + gravação de auditoria na edição de centros | |
| 6 | Painel comparativo entre atletas da mesma turma | Ajuda o professor a priorizar o treino do dia | 🟡 | Não iniciado |
| 7 | Lista de espera de interessados | Cadastro e acompanhamento de interessados aguardando vaga no centro | 🟡 | ✅ Construído |
| 8 | Ferramentas administrativas de manutenção do banco | Apagar dados de um centro, recarregar catálogo oficial, backup | 🟠 | ✅ Construído (parcial — backup ainda é um placeholder) |
| 9 | Módulo Calendário | Registro de datas relevantes (eventos, competições, feriados etc.) com visão dia/semana/mês/agenda (react-big-calendar) | 🟠 | ✅ Construído |
| 10 | Módulo Alertas | Avisos em destaque no dashboard, disparados por SUPER_ADMIN (plataforma) ou GESTOR (próprio centro), com criticidade, alvo (todos/papel) e período de exibição | 🟠 | ✅ Construído |
| 11 | Dias/horários de aula por turma | Turma registra em quais dias da semana tem aula e o horário de início/término de cada dia | 🟡 | ✅ Construído |
| 12 | Módulos por perfil (matriz de acesso) | SUPER_ADMIN habilita/desabilita cada módulo por papel, com auditoria da alteração | 🟠 | ✅ Construído |
Futuro
| # | Funcionalidade | Objetivo | Prioridade |
|---|---|---|---|
| 1 | Integração com WhatsApp | Lembretes de treino, avisos de pagamento, notificação de nova observação (via API oficial do WhatsApp Business) | 🟢 |
| 2 | Apps nativos (React Native) | Caso o uso mobile via PWA mostre necessidade real de recursos nativos (push robusto, câmera) | 🟢 |
| 3 | Sugestão assistida de série / alerta de carga de treino | Uso de dados históricos para sugerir progressão ou sinalizar risco de sobrecarga | 🟢 |
| 4 | Integração com federações (FGE/CBG) | Inscrição de atletas em competições oficiais | 🟢 |
| 5 | Multi-idioma / expansão internacional | Suporte a outros países de língua portuguesa/espanhola | 🟢 |
7. Fluxos
7.1 Jornada completa (primeiro acesso do gestor)
- Entrada: gestor acessa a landing page pública e clica em "Criar conta".
- Autenticação: informa nome, e-mail, senha → conta criada, e-mail de confirmação enviado.
- Onboarding: wizard de 3 passos — dados do centro (nome, CNPJ opcional, tipo) → escolha do plano (FREE pré-selecionado) → convite do primeiro professor (opcional, pode pular).
- Utilização: cai no dashboard vazio, com atalhos guiados ("Cadastre sua primeira turma", "Cadastre sua primeira atleta").
- Conclusão da tarefa: cadastra turma → cadastra atleta → monta série → registra primeiro treino.
- Saída: logout ou fechamento da aba; sessão expira em 30 dias (refresh) ou ao logout explícito.
Pontos de fricção identificados: (a) montar a primeira série do zero pode intimidar quem não conhece bem o catálogo FIG — mitigado com um filtro guiado por aparelho e busca por nome; (b) cadastro de atleta menor pede dado de um terceiro (responsável) que pode não estar por perto — mitigado permitindo salvar a atleta com o convite do responsável pendente, sem bloquear o cadastro.
7.2 Login e recuperação de senha
- Ponto inicial: tela de login.
- Ações: e-mail + senha.
- Validações: formato de e-mail; rate limit por IP+e-mail (10 tentativas / 5 min).
- Processamento: verifica hash da senha; gera JWT de sessão.
- Resposta: redireciona ao dashboard do papel do usuário.
- Erros possíveis: credenciais inválidas (mensagem genérica, nunca revela se o e-mail existe), conta desativada, rate limit excedido, sessão expirada em uso posterior (redireciona ao login preservando a URL de destino).
- Estado final: sessão ativa ou usuário de volta ao login com mensagem clara.
7.3 Montagem de série
- Ponto inicial: perfil da atleta → aba "Série".
- Ações: escolher aparelho, buscar/filtrar movimento no catálogo, adicionar à série, reordenar (drag-and-drop com alternativa por botões ↑/↓ para acessibilidade), remover.
- Validações: não permite movimento duplicado na mesma série; exige ao menos 1 movimento para salvar.
- Processamento: recalcula valor de dificuldade total a cada alteração.
- Resposta: salva e mostra valor total atualizado.
- Erros possíveis: falha de rede ao salvar (mantém rascunho local e permite tentar novamente); tentativa de editar série de atleta de outro tenant (bloqueado no servidor, 403).
- Estado final: série vigente da atleta atualizada, versão anterior mantida no histórico.
7.4 Registro de treino
- Ponto inicial: professor abre "Novo treino" a partir da turma ou da atleta.
- Ações: seleciona data (padrão: hoje), seleciona atletas presentes, para cada atleta marca executado/não executado por movimento da série vigente, escreve observação geral opcional.
- Validações: não permite registrar treino em data futura; não permite dois treinos da mesma turma na mesma data sem confirmação explícita (evita duplicidade acidental).
- Processamento: grava
Treino+TreinoAtleta+TreinoSerieExecucaopor movimento. - Resposta: confirmação de treino registrado, retorno à lista de treinos da turma.
- Erros possíveis: sessão expirada no meio do preenchimento (mantém dados em rascunho local até reautenticar); atleta sem série vigente (bloqueia registro dessa atleta especificamente, sem travar a turma toda).
- Estado final: histórico de treino consultável na evolução da atleta.
7.5 Consulta de evolução
- Ponto inicial: perfil da atleta → aba "Evolução".
- Ações: filtrar por período, por aparelho, alternar entre visão gráfico/tabela.
- Validações: papel
ATLETA/RESPONSAVELsó pode consultar a própria atleta vinculada. - Processamento: agrega execuções por movimento (taxa de acerto) e evolução do valor de dificuldade dominado ao longo do tempo.
- Resposta: gráfico de linha/barra (Recharts) + tabela detalhada exportável (V2).
- Erros possíveis: sem dados ainda (estado vazio orientando a registrar o primeiro treino); falha ao carregar (mensagem amigável + tentar novamente).
- Estado final: nenhuma alteração de dado, é uma tela somente leitura.
8. Telas
| Tela | Perfis | Objetivo | Componentes/estados principais |
|---|---|---|---|
| Login | Todos | Autenticar | Form, erro de credencial, loading no botão |
| Recuperar/Definir senha | Todos | Reset de senha | Form, sucesso, link expirado |
| Onboarding do centro | Gestor | Criar tenant e primeiro acesso | Wizard 3 passos, validação por passo |
| Dashboard | Todos (conteúdo varia por papel) | Visão geral | Cards de indicador, atalhos, estado vazio guiado |
| Centros (lista) | Super Admin | Administrar tenants | Tabela com busca/filtro/paginação, badge de status, ações (ver/editar/desativar) |
| Centro (detalhe/edição) | Super Admin | Ver e editar todos os dados do tenant | Form completo: nome, slug, CNPJ, tipo, grupo (matriz/filial), plano, status, contato, e-mail, endereço com busca por CEP |
| Usuários (lista) | Gestor | Gerenciar equipe/atletas/responsáveis | Tabela com filtro por papel, ações (editar/desativar/reenviar convite) |
| Convite/edição de usuário | Gestor | Criar/editar usuário | Form, seleção de papel |
| Turmas (lista) | Gestor/Professor | Gerenciar turmas | Tabela/cards com busca, paginação, ação criar |
| Turma (edição) | Gestor/Professor | Editar turma e gerenciar atletas vinculadas | Form + lista de atletas para adicionar/remover |
| Equipes (lista/detalhe) | Gestor/Professor | Gerenciar equipes e membros | Tabela/cards, gestão de membros titular/reserva, atalho para montar série da equipe |
| Responsáveis (lista) | Gestor/Professor | Consultar responsáveis vinculados a atletas | Tabela/cards com busca, paginação |
| Lista de espera (lista/detalhe/edição) | Gestor/Professor | Gerenciar interessados aguardando vaga | Tabela/cards, filtro por status, form de cadastro/edição |
| Atletas (lista) | Gestor/Professor | Gerenciar atletas | Tabela/cards com busca, filtro por turma, ações (ver/editar/inativar) |
| Atleta (perfil) | Gestor/Professor/Atleta/Responsável | Ver dados, série vigente, histórico, evolução | Abas: Dados · Série · Treinos · Evolução |
| Catálogo de movimentos (lista) | Todos (edição restrita) | Consultar movimentos | Filtro por aparelho/grupo, busca, imagem+símbolo+valor por item |
| Movimento (detalhe) | Todos | Ver detalhes do movimento | Imagem, símbolo, aparelho, grupo, valor, descrição |
| Movimento (criar/editar customizado) | Gestor/Professor | Cadastrar movimento próprio do centro | Form com upload de imagem |
| Montagem de série | Professor | Montar/editar série da atleta | Lista ordenável, busca de movimento, valor total calculado |
| Novo treino / Registro de treino | Professor/Gestor | Registrar execução do dia | Checklist por atleta/movimento, campo de observação |
| Treino (detalhe) | Gestor/Professor/Atleta/Responsável | Consultar um treino registrado | Presença, execução por movimento (executado/não executado), observações |
| Treinos (histórico) | Gestor/Professor/Atleta/Responsável | Consultar treinos passados | Tabela/cards, filtro por turma, paginação |
| Competições (lista/registro) | Gestor/Professor | Cadastrar competição e resultados | Form + tabela de resultados por atleta |
| Evolução da atleta | Todos (dados restritos ao papel) | Gráfico/tabela de progresso | Toggle gráfico/tabela, filtro por aparelho e período |
| Mensagens (recebidas/enviadas) | Gestor/Professor | Trocar mensagens dentro da plataforma (menu Comunicação) | Abas Recebidas/Enviadas, campo de destinatários estilo e-mail, responder com thread, leitura automática ao abrir |
| Calendário | Todos (edição restrita a Gestor/Professor) | Visualizar e gerenciar eventos relevantes | Componente de calendário (react-big-calendar) com visão dia/semana/mês/agenda; lista de próximos eventos no dashboard |
| Evento de calendário (criar/editar/detalhe) | Gestor/Professor | Cadastrar evento: título, tipo, local, dia inteiro ou início/término, descrição | Form + confirmação de exclusão |
| Alertas (lista) | Todos | Consultar alertas | Abas "Recebidos" (histórico de lidos) e "Criados por mim" (Gestor/Super Admin) |
| Alerta (criar/editar/detalhe) | Super Admin, Gestor | Disparar/gerenciar alerta: título, mensagem, criticidade, alvo (todos/papel), período de exibição | Form + seletor de alvo (todos ou papel específico) + confirmação de exclusão |
| Módulos por perfil | Super Admin | Habilitar/desabilitar módulos por papel | Seletor de papel (aba), matriz de ações (visualizar/cadastrar/editar/deletar) por módulo, salvar com feedback |
| Logs | Super Admin | Consultar a trilha de auditoria | Tabela com filtro por centro/ação/entidade/módulo, paginação |
| Banco de dados | Super Admin | Ferramentas de manutenção do banco | Apagar dados de um centro (com confirmação), recarregar catálogo oficial, backup (placeholder) |
| Meu perfil | Todos | Dados pessoais, foto, endereço, senha | Form completo com upload de foto e busca de endereço por CEP |
| Configurações do centro | Gestor | Dados do tenant, plano (somente leitura no MVP) | Form parcialmente bloqueado |
| 404 / Erro | Todos | Estado de exceção | Já implementado na Fase 1 |
Todas as telas de listagem seguem o mesmo padrão: busca, filtros, paginação, e ações representadas por ícones com tooltip (ver, editar, excluir/inativar) em vez de texto, para economizar espaço e ficar consistente em mobile.
9. UX/UI
Reaproveita a identidade já definida no brand kit do Rythmiq e já implementada no scaffold:
- Paleta: Rythmiq Indigo
#17104F(base estrutural/fundo), Deep Purple#4B1C92, Vibrant Magenta#E52B8Fe Soft Pink#F28AC7(destaque/ações primárias), Lilac#DCC7F5(texto secundário/apoio sobre fundo escuro), White. - Tipografia: Poppins (títulos, 600–700) e Inter (texto/interface, 400–500), já carregadas via
next/font. - Layout padrão: sidebar fixa com navegação (colapsa para menu inferior/drawer no mobile), header com breadcrumb do caminho atual e menu de perfil/configurações no canto superior direito — mesmo padrão de projetos anteriores, já validado com usuários reais daquele produto.
- Componentes: cards para dashboards e listas em mobile; tabelas com paginação para listas em desktop; badges de status coloridos (ativo/inativo, executado/não executado); botões primários em
marca-magenta; ações de linha (ver/editar/excluir) como ícones com área de toque de 44px mínimo. - Estados de interação: todo componente interativo tem estado hover, focus visível (contorno, nunca só cor) e disabled com cursor
not-allowed. - Acessibilidade: contraste mínimo AA em todos os textos sobre
marca-indigo; navegação 100% por teclado; labels associados a todo input; mensagens de erro anunciadas viaaria-live.
10. Responsividade
| Faixa | Comportamento |
|---|---|
| 320–414px (mobile) | Sidebar vira menu inferior fixo (ícones) + drawer para itens secundários; tabelas viram lista de cards; formulários em coluna única; modais ocupam a tela cheia; filtros ficam atrás de um botão "Filtrar" |
| Tablet (~768px) | Sidebar colapsada (só ícones), expande sob demanda; tabelas com colunas prioritárias, scroll horizontal para o restante |
| Notebook/Desktop (≥1280px) | Sidebar expandida com rótulos; tabelas completas; modais centralizados com largura máxima |
| Telas grandes (≥1600px) | Conteúdo com max-width central para não esticar demais texto e cards |
A navegação, os formulários e as tabelas são desenhados mobile-first e depois enriquecidos para telas maiores — nunca o inverso.
11. Arquitetura
Monólito modular em Next.js (App Router), mesmo padrão de projetos anteriores: frontend e backend no mesmo processo, via Server Actions/Route Handlers. Multi-tenancy por coluna tenantId com isolamento reforçado em um helper de escopo de tenant no servidor (nunca confiar em tenantId vindo do cliente). TenantGroup é a única estrutura nova para representar matriz/filial. PostgreSQL como banco único. Armazenamento de objetos (imagens de movimentos, ícone do centro) em bucket S3-compatível. Sem filas/processamento assíncrono pesado no MVP — volume de dados inicial não justifica; e-mails transacionais são enviados de forma síncrona via provedor com fila própria. Um monólito modular é suficiente para o tamanho do projeto; microserviços seriam complexidade prematura.
12. Stack tecnológica
| Camada | Escolha | Motivo |
|---|---|---|
| Frontend | Next.js 15 + React 19 + TypeScript + Tailwind | Já em uso no scaffold; um único framework cobre SSR, rotas e API |
| Backend | Route Handlers/Server Actions do próprio Next.js | Evita um segundo serviço/deploy para um projeto deste porte |
| Banco de dados | PostgreSQL + Prisma ORM | Relacional se encaixa bem no domínio (tenants, papéis, séries, treinos); Prisma já validado no scaffold |
| Autenticação | NextAuth (Credentials, sessão JWT) | Já implementado; evita reinventar hashing/sessão |
| Armazenamento de arquivos | Cloudflare R2 ou Supabase Storage | S3-compatível, custo baixo, sem egress caro (R2) |
| E-mail transacional | Resend | Boa DX com Next.js, fila própria, custo baixo em volume inicial |
| Gráficos | Recharts | Leve, componível em React, suficiente para linha/barra de evolução |
| Hospedagem/Deploy | Vercel (app) + Neon/Supabase (Postgres gerenciado) | Deploy contínuo por PR, zero ops para o tamanho atual do projeto |
| Monitoramento de erros | Sentry | Padrão de mercado, integra bem com Next.js |
| Testes | Vitest (unit/integração) + Playwright (E2E) | Já no scaffold |
13. Banco de dados
13.1 Modelo conceitual (entidades principais)
TenantGroup (1—N) Tenant (1—N) User, Turma, Atleta, Movimento (customizado), Serie, Treino, Competicao.
Turma (1—N) Atleta. Atleta (1—1) Serie vigente por aparelho, (1—N) Serie histórico. Serie (1—N) SerieMovimento → Movimento. Treino (1—N) TreinoAtleta (1—N) TreinoSerieExecucao → SerieMovimento. Atleta (1—N) ResultadoCompeticao ← Competicao.
13.2 Schema inicial (Prisma, resumido)
O schema abaixo é a versão representativa aprovada aqui. O implementado em
prisma/schema.prismaé o mesmo modelo com rigor adicional (relações nomeadas para múltiplas FKs ao mesmo modelo,@@mappara nomes de tabela em snake_case, e um modeloSenhaConvitepara o fluxo de convite de usuário sem senha ainda definida) —prisma/schema.prismaé a fonte da verdade em caso de divergência.
enum Role {
SUPER_ADMIN
GESTOR
PROFESSOR
ATLETA
RESPONSAVEL
}
enum TenantTipo {
MATRIZ
FILIAL
INDEPENDENTE
}
enum Plano {
FREE
INDIVIDUAL
CENTRO_DE_TREINAMENTO
}
enum TenantStatus {
TRIAL
ATIVO
INATIVO
}
enum Aparelho {
MAOS_LIVRES
ARCO
BOLA
MACAS
FITA
}
enum GrupoDificuldade {
SALTO
EQUILIBRIO
ROTACAO
FLEXIBILIDADE_ONDA
DIFICULDADE_APARELHO
}
model TenantGroup {
id String @id @default(cuid())
nome String
tenants Tenant[]
}
model Tenant {
id String @id @default(cuid())
tenantGroupId String?
tenantGroup TenantGroup? @relation(fields: [tenantGroupId], references: [id])
nome String
slug String @unique
cnpj String? @unique
tipo TenantTipo @default(INDEPENDENTE)
plano Plano @default(FREE)
status TenantStatus @default(TRIAL)
createdAt DateTime @default(now())
users User[]
}
model User {
id String @id @default(cuid())
tenantId String?
tenant Tenant? @relation(fields: [tenantId], references: [id])
nome String
email String @unique
senhaHash String
role Role
ativo Boolean @default(true)
deletedAt DateTime?
createdAt DateTime @default(now())
}
model Turma {
id String @id @default(cuid())
tenantId String
nome String
professorId String?
atletas Atleta[]
@@index([tenantId])
}
model Atleta {
id String @id @default(cuid())
tenantId String
nome String
dataNascimento DateTime
turmaId String?
turma Turma? @relation(fields: [turmaId], references: [id])
responsavelId String?
ativo Boolean @default(true)
deletedAt DateTime?
createdAt DateTime @default(now())
@@index([tenantId])
}
model Movimento {
id String @id @default(cuid())
tenantId String? // null = catálogo oficial global
codigo String
nome String
aparelho Aparelho
grupoDificuldade GrupoDificuldade
valorDificuldade Decimal @db.Decimal(3, 2)
imagemUrl String?
simboloUrl String?
descricao String?
oficial Boolean @default(true)
@@index([tenantId])
@@index([aparelho, grupoDificuldade])
}
model Serie {
id String @id @default(cuid())
tenantId String
atletaId String
atleta Atleta @relation(fields: [atletaId], references: [id])
aparelho Aparelho
vigente Boolean @default(true)
criadaEm DateTime @default(now())
movimentos SerieMovimento[]
@@index([tenantId, atletaId, aparelho])
}
model SerieMovimento {
id String @id @default(cuid())
serieId String
serie Serie @relation(fields: [serieId], references: [id])
movimentoId String
movimento Movimento @relation(fields: [movimentoId], references: [id])
ordem Int
}
model Treino {
id String @id @default(cuid())
tenantId String
turmaId String?
data DateTime
professorId String
observacoesGerais String?
atletas TreinoAtleta[]
@@index([tenantId, data])
}
model TreinoAtleta {
id String @id @default(cuid())
treinoId String
treino Treino @relation(fields: [treinoId], references: [id])
atletaId String
presente Boolean @default(true)
execucoes TreinoSerieExecucao[]
}
model TreinoSerieExecucao {
id String @id @default(cuid())
treinoAtletaId String
treinoAtleta TreinoAtleta @relation(fields: [treinoAtletaId], references: [id])
serieMovimentoId String
serieMovimento SerieMovimento @relation(fields: [serieMovimentoId], references: [id])
executado Boolean
observacao String?
}
model Competicao {
id String @id @default(cuid())
tenantId String
nome String
data DateTime
local String?
resultados ResultadoCompeticao[]
@@index([tenantId, data])
}
model ResultadoCompeticao {
id String @id @default(cuid())
competicaoId String
competicao Competicao @relation(fields: [competicaoId], references: [id])
atletaId String
aparelho Aparelho
nota Decimal @db.Decimal(5, 3)
colocacao Int?
}
model AuditLog {
id String @id @default(cuid())
tenantId String?
userId String?
acao String
entidade String
entidadeId String
metadata Json?
createdAt DateTime @default(now())
@@index([tenantId, createdAt])
}
Todas as tabelas de escopo de tenant têm índice em tenantId. Soft delete (deletedAt) em User e Atleta, onde exclusão definitiva perderia histórico de valor (treinos, séries). Constraint de unicidade em User por (tenantId, email) — não globalmente: uma pessoa pode atuar em mais de um centro com o mesmo e-mail, mesmo padrão de projetos anteriores — e em Tenant.slug/Tenant.cnpj.
13.3 Modelos adicionados nesta fase (Calendário, Alertas, horários de turma)
TurmaHorario— dias/horários de aula da turma:turmaId,diaSemana(enumDiaSemana, SEGUNDA→DOMINGO),horaInicio/horaFim(String, formatoHH:mm);@@unique([turmaId, diaSemana])(um horário por dia por turma); substituição completa (delete+create) a cada edição da turma, mesmo padrão já usado emPlanoModulo/PerfilModulo.EventoCalendario— evento do módulo Calendário:tenantId,titulo,tipo(enumTipoEventoCalendario),local?,diaInteiro,dataInicio/dataFim?,descricao?,criadoPorId. Renderizado comreact-big-calendar(visões dia/semana/mês/agenda); os N próximos eventos aparecem no dashboard de todos os papéis.Alerta— aviso em destaque no dashboard:tenantId?(nulo = broadcast de plataforma disparado pelo SUPER_ADMIN para todos os tenants; preenchido = alerta do GESTOR restrito ao próprio centro),titulo,mensagem,criticidade(enumCriticidadeAlerta: INFORMATIVO/ATENCAO/ALTA/CRITICA — cor e ícone no dashboard variam por nível),alvo(enumAlertaAlvo: TODOS ou PERFIL),perfilAlvo?(papel-alvo quandoalvo = PERFIL),dataInicio/dataFim?(janela de exibição),criadoPorId. Só SUPER_ADMIN e GESTOR podem disparar.AlertaLeitura— join table de leitura por usuário:alertaId,userId,lidoEm;@@unique([alertaId, userId]). Ausência de registro = alerta pendente (aparece em destaque); presença = já lido/fechado (some do destaque, aparece no histórico "Recebidos").POST /api/alertas/:id/marcar-lidofazupsert(idempotente).AuditLog.modulo— campo adicional (Modulo?, opcional) na tabela de auditoria já existente, para permitir filtrar/consultar por módulo do sistema (enumModulo) além do texto livre já existente ementidade. Usado inicialmente nas alterações da matriz de Módulos por perfil; demais pontos de auditoria continuam usando apenasentidade.
A visibilidade de um alerta para um usuário combina duas condições: (mesmo tenant OU alerta de plataforma) E (alvo = TODOS OU papel do usuário = perfilAlvo).
14. APIs
Endpoints representativos (Route Handlers do Next.js). Todos exigem sessão exceto onde indicado; toda query de dado de tenant passa pelo helper de escopo de tenant no servidor.
| Método | Rota | Auth | Descrição |
|---|---|---|---|
| POST | /api/auth/[...nextauth] | — | Login/logout (NextAuth) |
| POST | /api/onboarding | Pública (cria conta) | Cria tenant + primeiro usuário GESTOR |
| GET/POST | /api/tenants | SUPER_ADMIN | Listar/criar centros |
| GET/PATCH | /api/tenants/:id | SUPER_ADMIN | Ver/editar centro |
| GET/POST | /api/usuarios | GESTOR | Listar/convidar usuários do tenant |
| PATCH | /api/usuarios/:id | GESTOR | Editar papel/ativar/desativar |
| GET/POST | /api/turmas | GESTOR, PROFESSOR | Listar/criar turmas |
| GET/POST | /api/atletas | GESTOR, PROFESSOR | Listar/criar atletas |
| GET/PATCH | /api/atletas/:id | GESTOR, PROFESSOR, ATLETA*, RESPONSAVEL* | Ver/editar atleta (*somente a própria) |
| GET | /api/movimentos | Todos | Listar catálogo (filtro aparelho/grupo) |
| POST | /api/movimentos | GESTOR, PROFESSOR | Criar movimento customizado do tenant |
| GET/PUT | /api/atletas/:id/series/:aparelho | GESTOR, PROFESSOR | Ver/atualizar série vigente |
| GET/POST | /api/treinos | GESTOR, PROFESSOR | Listar/registrar treino |
| GET/POST | /api/competicoes | GESTOR, PROFESSOR | Listar/registrar competição e resultados |
| GET | /api/atletas/:id/evolucao | GESTOR, PROFESSOR, ATLETA*, RESPONSAVEL* | Dados agregados para gráfico/tabela |
| GET/POST | /api/eventos-calendario | Todos (criação: GESTOR, PROFESSOR) | Listar/criar evento do Calendário |
| GET/PATCH/DELETE | /api/eventos-calendario/:id | Todos leitura; GESTOR/PROFESSOR edição/exclusão | Ver/editar/excluir evento |
| GET/POST | /api/alertas | SUPER_ADMIN, GESTOR (criação) | Listar alertas criados pelo usuário / disparar novo alerta |
| GET/PATCH/DELETE | /api/alertas/:id | Criador do alerta (edição/exclusão); destinatário (leitura) | Ver/editar/excluir alerta |
| GET | /api/alertas/ativos | Todos (autenticado, com tenant) | Alertas ativos ainda não lidos pelo usuário (banner do dashboard) |
| POST | /api/alertas/:id/marcar-lido | Todos (autenticado, com tenant) | Marca o alerta como lido (idempotente); usado ao fechar o banner |
| GET/PUT | /api/perfil-modulos | SUPER_ADMIN | Ver/salvar a matriz de módulos habilitados por papel (?role= filtra um papel) |
Exemplo:
POST /api/atletas
Auth: sessão GESTOR ou PROFESSOR do tenant
Request:
{
"nome": "Maria Silva",
"dataNascimento": "2014-03-10",
"turmaId": "clx123",
"responsavelId": "clx456"
}
Response 201:
{
"id": "clx789",
"nome": "Maria Silva",
"turmaId": "clx123"
}
Erros:
400 — dado inválido ou responsável ausente para atleta menor
403 — usuário sem permissão no tenant
409 — nada a reportar (sem unicidade neste recurso)
15. Segurança
- Autenticação/autorização: sessão JWT (NextAuth); toda rota de API valida papel e tenant no servidor, nunca no cliente.
- Isolamento multi-tenant: helper único de escopo (
tenantScope) usado em toda query — mesmo mecanismo de projetos anteriores, já testado em produção; nenhuma query manual sem esse escopo. - Least privilege: matriz de permissões (seção 6) aplicada em cada endpoint; RESPONSAVEL e ATLETA são somente leitura dos próprios dados.
- Rate limiting: login (10 tentativas/5min por IP+e-mail), criação de conta (mitiga abuso de onboarding).
- Validação e sanitização: Zod em toda entrada; upload de imagem de movimento restrito a tipo/tamanho, nome de arquivo sanitizado, sem aceitar SVG (risco de XSS via SVG malicioso).
- Segredos: nunca em código; variáveis de ambiente, com falha alta se
AUTH_SECRETausente em produção (já implementado). - Cabeçalhos HTTP: CSP restritiva, HSTS, X-Frame-Options, X-Content-Type-Options (já implementado no
next.config.js). - Auditoria: tabela
AuditLogpara ações sensíveis (mudança de papel, exclusão, alteração de tenant). - LGPD: dado de menor tratado com consentimento do responsável no cadastro; direito de exclusão via soft delete + anonimização em job futuro; nenhum dado sensível em log técnico.
16. Testes
- Unitários: cálculo de valor de dificuldade da série; regras de transição de estado (ex.: série vigente x histórica); schemas Zod.
- Integração: cada endpoint de API testado com dois tenants distintos para garantir que um nunca vê dado do outro.
- E2E (Playwright): onboarding completo → cadastro de turma/atleta → montagem de série → registro de treino → consulta de evolução.
- Segurança: tentativa de acesso cross-tenant (deve retornar 403/404, nunca vazar existência do recurso); brute force de login; upload de arquivo malicioso.
- Responsividade: verificação visual em 375px, 768px e 1280px das telas de listagem, formulário e evolução.
17. Estrutura do projeto
Reaproveita a estrutura já criada no scaffold (mesma de projetos anteriores):
src/
├── app/ # rotas (App Router), agrupadas por área: (auth), (app)
├── components/ # componentes de UI reutilizáveis
├── lib/
│ ├── auth/ # config do NextAuth
│ ├── db/ # cliente Prisma
│ ├── tenant/ # helper de escopo de tenant
│ ├── security/ # rate limit, etc.
│ └── validation/ # schemas Zod por entidade
├── server/
│ ├── api/ # handlers HTTP compartilhados (erros, csrf)
│ └── services/ # regra de negócio por entidade (movimentos, series, treinos, ...)
└── types/
prisma/
├── schema.prisma
├── seed.ts # inclui o seed do catálogo oficial de movimentos FIG
└── migrations/
docs/
└── especificacao-produto.md # este documento
18. Roadmap
| Fase | Escopo |
|---|---|
| 1 — Fundação | ✅ Scaffold Next.js/Prisma/NextAuth/Tailwind, identidade visual aplicada, schema completo migrado (TenantGroup, 5 papéis), NextAuth multi-tenant (email único por tenant) |
| 2 — Core | ✅ Seed do catálogo FIG (35 movimentos), services e API de tenants/usuários (convite)/turmas/atletas/movimentos/séries/treinos/competições/evolução, isolamento multi-tenant testado. Falta: telas (layout padrão, onboarding wizard, dashboard, CRUDs) |
| 3 — UX | ✅ Layout padrão (sidebar/header/breadcrumb, responsivo com bottom-nav mobile), tela de login redesenhada (cartão + branding), onboarding self-service, dashboard e CRUDs de turmas/atletas/movimentos (com imagem/símbolo e status ativo/descontinuado/excluído)/treinos (com filtro por atleta)/competições/usuários/centros, listagem dedicada de séries (filtros + histórico) e perfil da atleta com abas. Falta: estados de loading/skeleton dedicados (hoje é só texto), exportação de relatórios, comparação entre atletas |
| 4 — Segurança | Hardening do isolamento de tenant, rate limiting ampliado, AuditLog, revisão LGPD |
| 5 — Testes | Suítes unit/integração/E2E da seção 16 |
| 6 — Deploy | Ambientes (dev/staging/produção), CI/CD, Sentry, backups do Postgres gerenciado |
| 7 — Evolução | Cobrança de planos, comunicação interna, financeiro de mensalidades, integração WhatsApp |
19. Critérios de aceitação (exemplos)
Cadastro de atleta
- Deve exigir nome e data de nascimento.
- Se a atleta for menor de 18 anos, deve exigir um responsável vinculado.
- Não permite duas atletas idênticas (nome + data de nascimento) no mesmo tenant sem confirmação explícita.
- Após salvar, exibe confirmação de sucesso e retorna à lista.
Montagem de série
- Deve permitir adicionar/remover/reordenar movimentos do catálogo.
- O valor de dificuldade total deve recalcular automaticamente a cada alteração.
- Não permite salvar série vazia.
Registro de treino
- Deve permitir marcar executado/não executado por movimento da série vigente.
- Não permite registrar treino com data futura.
- Após salvar, o dado aparece imediatamente na tela de evolução da atleta.
Isolamento multi-tenant
- Um usuário de um tenant nunca deve conseguir visualizar, editar ou excluir dado de outro tenant, mesmo manipulando IDs diretamente na requisição.
20. Riscos e pontos de atenção
- Fidelidade ao Código FIG: a estrutura de aparelho/grupo/valor cobre o essencial, mas o código oficial tem nuances (penalidades, elementos de conjunto, mudanças de regulamento a cada ciclo olímpico). Recomenda-se validar o catálogo semeado com um técnico/juiz de GR antes do lançamento.
- Propriedade intelectual: não reproduzir símbolos/desenhos oficiais da FIG; usar ilustração própria do Rythmiq.
- LGPD com menores de idade: recomenda-se revisão jurídica do fluxo de consentimento antes da comercialização.
- Plano sem gating no MVP: como o campo "plano" ainda não limita uso, é preciso comunicar isso claramente para não criar expectativa errada com os primeiros clientes.
- Ausência de benchmark: por não haver concorrente direto, validar cedo com um centro piloto real é mais importante do que polir detalhes de UI antes do primeiro uso real.
- Matriz/filial com
TenantGroup: acessar dados de múltiplas filiais a partir de um único login de gestor de rede é uma necessidade que pode surgir cedo; hoje o modelo permite o agrupamento cadastral, mas a tela de "visão consolidada da rede" ainda não está no MVP — mapeado para V2/Futuro conforme a demanda real aparecer.
Próximo passo recomendado
Seguir a sequência Planejamento → Arquitetura → Banco → Backend → API → Frontend → UX/UI → Testes → Segurança → Deploy, começando por:
- Migrar o schema Prisma completo da seção 13 (substituindo o
Usermínimo atual). - Popular o seed com o catálogo oficial de movimentos FIG (aparelho, grupo, valor) usando ilustração própria.
- Ampliar o NextAuth para os 5 papéis e implementar o layout padrão (sidebar + header + breadcrumb) reaproveitando o padrão de projetos anteriores.
Cada etapa fecha com uma checagem de consistência (telas ↔ funcionalidades ↔ regras ↔ banco ↔ API) antes de avançar para a próxima, conforme pedido no prompt de arquitetura.