VoltarEspecificação do produto

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:

#PerguntaDecisão
1Alcance de plataforma (app nativo x web)?Web responsivo, instalável como PWA. Sem apps nativos por ora.
2Como matriz/filial se relacionam nos dados?Tenants separados, agrupados por um TenantGroup opcional.
3Como 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

PersonaPerfilObjetivo na plataformaNecessidadesDificuldades hoje
Gestora do centro (papel GESTOR)Dona/diretora de um centro de treinamento, gerencia de 1 a várias turmas e professoresTer visão consolidada do centro: quantas atletas, quantos professores, adimplência (futuro)Cadastro simples de turmas/professores/atletas, visão gerencial rápidaPlanilhas soltas por professor, sem padronização, sem histórico centralizado
Professor(a)/treinador(a) (papel PROFESSOR)Ministra os treinos, monta e ajusta as sériesRegistrar rapidamente, durante ou logo após o treino, o que cada atleta executouRegistro rápido (poucos toques), no celular/tablet à beira do tapeteAnotar 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 idadeAcompanhar a própria evolução e a série atualVisão simples do que já executa bem e do que precisa treinar maisNã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 idadeAcompanhar a evolução da filha/tutelada, sem se envolver na operação do treinoVisã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 tenantAdministrar a plataforma: cadastro de centros, planos, suporteVisão de todos os tenants, ferramentas de suporte e auditoriaN/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óduloSuper AdminGestorProfessorAtletaResponsá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 perfilHabilita/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 perfilEditar dados pessoais, foto, endereço e trocar senhaEditar dados pessoais, foto, endereço e trocar senhaEditar dados pessoais, foto, endereço e trocar senhaEditar dados pessoais, foto, endereço e trocar senhaEditar 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 completoCRUD completoConsulta a própria fichaConsulta 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 atletasConsulta——
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 centroConsulta e cria movimento customizado do centroConsultaConsulta
Séries—Monta e edita a série da atleta/equipe por aparelhoMonta e edita a série da atleta/equipe por aparelhoConsulta a própriaConsulta a da tutelada
Treinos—Registra e consulta o históricoRegistra e consulta o históricoConsulta o próprio histórico e execução por movimentoConsulta o histórico da tutelada
Competições—Registra competição e resultado por atletaRegistra competição e resultado por atletaConsultaConsulta
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/agendaCRUD de eventosConsultaConsulta
Comunicação → Mensagens—Envia, responde (com histórico de thread) e marca como lida automaticamente ao abrirEnvia, responde e marca como lida automaticamente ao abrir——
AlertasDispara para toda a plataforma (todos os tenants), para TODOS os usuários ou só um papel; gerencia os própriosDispara para o próprio centro, para TODOS os usuários ou só um papel; gerencia os própriosRecebe, 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ávelIdemIdem, restrito aos próprios dadosIdem, restrito à tutelada

MVP

#FuncionalidadeUsuárioObjetivo / fluxo resumidoRegras de negócio principaisDependênciasPrioridade
1Autenticação (login, recuperar senha)TodosLogin por e-mail/senha; fluxo de "esqueci minha senha" por e-mailRate limit de tentativas; sessão JWT; senha com requisitos mínimos—🔴
2Onboarding do centroGestor (self-service)Wizard: dados do centro → plano desejado → convite do primeiro professorCria Tenant em status TRIAL; e-mail do gestor vira o primeiro User com papel GESTORAuth🔴
3Cadastro de tenants (centros)Super AdminCRUD de centros: nome, CNPJ, tipo (matriz/filial/independente), TenantGroup, plano, status ativo/inativoCNPJ único quando informado; filial deve referenciar uma matriz existente—🔴
4Gestão de usuários do centroGestorConvidar/editar/desativar professor, atleta, responsávelE-mail único na plataforma; só GESTOR gerencia usuários do próprio tenantOnboarding🔴
5Catá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 centroMovimento oficial (oficial = true) não pode ser editado/excluído pelo tenant; valor de dificuldade em incrementos de 0,10—🔴
6Cadastro de turmasGestor/ProfessorCRUD de turma: nome, professor responsávelTurma pertence a um único tenantUsuários🔴
7Cadastro de atletasGestor/ProfessorCRUD de atleta: dados pessoais, data de nascimento, turma; se menor, exige responsável vinculado + consentimentoAtleta menor sem responsável vinculado não pode ser salvaTurmas, Usuários🔴
8Montagem de sérieProfessorMonta a série da atleta por aparelho, escolhendo e ordenando movimentos do catálogoValor de dificuldade total da série calculado automaticamente pela soma dos movimentosMovimentos, Atletas🔴
9Registro de treinoProfessorAbre a série da atleta no dia do treino, marca executado/não executado por movimento, adiciona observação geralUm registro de treino por atleta por data; não pode registrar execução de movimento fora da série vigenteSéries🔴
10Registro simplificado de competiçãoProfessor/GestorCadastra competição (nome, data, local) e resultado por atleta/aparelho (nota final, colocação)Resultado sempre vinculado a uma atleta do próprio tenantAtletas🔴
11Evolução da atletaProfessor/Gestor/Atleta/ResponsávelGráfico e tabela de execução ao longo do tempo, por movimento e por aparelho; linha do tempo de competiçõesResponsável e Atleta só veem os próprios dadosTreinos, Competições🔴
12Layout padrão responsivoTodosSidebar com navegação, header com breadcrumb e menu de perfil, 320px→desktopSidebar colapsa em bottom-nav/drawer no mobile—🔴
13Dashboard inicial por perfilTodosIndicadores 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 papelDemais módulos🟠
14Configurações de contaTodosEditar nome, trocar senha, ver dados do próprio tenant (não editável por não-gestor)—Auth🟠

V2

#FuncionalidadeObjetivoPrioridadeStatus
1Cobrança de planos (assinatura)Ativar plano pago com cartão/boleto (ex.: via Stripe)🟠Não iniciado
2Gestão financeira simples de mensalidadesRegistrar mensalidade da atleta, status pago/pendente, vencimento🟡Não iniciado
3Área de comunicação internaMensagens entre gestor/professor/atleta/responsável dentro da plataforma🟡✅ Construído — módulo Mensagens (enviadas/recebidas, resposta com thread, leitura automática)
4Exportação de relatóriosPDF/Excel da evolução da atleta para reuniões e federações🟡Não iniciado
5Auditoria administrativaLog de ações sensíveis visível ao Super Admin🟠✅ Construído — tela de Logs + gravação de auditoria na edição de centros
6Painel comparativo entre atletas da mesma turmaAjuda o professor a priorizar o treino do dia🟡Não iniciado
7Lista de espera de interessadosCadastro e acompanhamento de interessados aguardando vaga no centro🟡✅ Construído
8Ferramentas administrativas de manutenção do bancoApagar dados de um centro, recarregar catálogo oficial, backup🟠✅ Construído (parcial — backup ainda é um placeholder)
9Módulo CalendárioRegistro de datas relevantes (eventos, competições, feriados etc.) com visão dia/semana/mês/agenda (react-big-calendar)🟠✅ Construído
10Módulo AlertasAvisos 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
11Dias/horários de aula por turmaTurma registra em quais dias da semana tem aula e o horário de início/término de cada dia🟡✅ Construído
12Módulos por perfil (matriz de acesso)SUPER_ADMIN habilita/desabilita cada módulo por papel, com auditoria da alteração🟠✅ Construído

Futuro

#FuncionalidadeObjetivoPrioridade
1Integração com WhatsAppLembretes de treino, avisos de pagamento, notificação de nova observação (via API oficial do WhatsApp Business)🟢
2Apps nativos (React Native)Caso o uso mobile via PWA mostre necessidade real de recursos nativos (push robusto, câmera)🟢
3Sugestão assistida de série / alerta de carga de treinoUso de dados históricos para sugerir progressão ou sinalizar risco de sobrecarga🟢
4Integração com federações (FGE/CBG)Inscrição de atletas em competições oficiais🟢
5Multi-idioma / expansão internacionalSuporte a outros países de língua portuguesa/espanhola🟢

7. Fluxos

7.1 Jornada completa (primeiro acesso do gestor)

  1. Entrada: gestor acessa a landing page pública e clica em "Criar conta".
  2. Autenticação: informa nome, e-mail, senha → conta criada, e-mail de confirmação enviado.
  3. 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).
  4. Utilização: cai no dashboard vazio, com atalhos guiados ("Cadastre sua primeira turma", "Cadastre sua primeira atleta").
  5. Conclusão da tarefa: cadastra turma → cadastra atleta → monta série → registra primeiro treino.
  6. 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

  1. Ponto inicial: tela de login.
  2. Ações: e-mail + senha.
  3. Validações: formato de e-mail; rate limit por IP+e-mail (10 tentativas / 5 min).
  4. Processamento: verifica hash da senha; gera JWT de sessão.
  5. Resposta: redireciona ao dashboard do papel do usuário.
  6. 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).
  7. Estado final: sessão ativa ou usuário de volta ao login com mensagem clara.

7.3 Montagem de série

  1. Ponto inicial: perfil da atleta → aba "Série".
  2. 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.
  3. Validações: não permite movimento duplicado na mesma série; exige ao menos 1 movimento para salvar.
  4. Processamento: recalcula valor de dificuldade total a cada alteração.
  5. Resposta: salva e mostra valor total atualizado.
  6. 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).
  7. Estado final: série vigente da atleta atualizada, versão anterior mantida no histórico.

7.4 Registro de treino

  1. Ponto inicial: professor abre "Novo treino" a partir da turma ou da atleta.
  2. 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.
  3. 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).
  4. Processamento: grava Treino + TreinoAtleta + TreinoSerieExecucao por movimento.
  5. Resposta: confirmação de treino registrado, retorno à lista de treinos da turma.
  6. 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).
  7. Estado final: histórico de treino consultável na evolução da atleta.

7.5 Consulta de evolução

  1. Ponto inicial: perfil da atleta → aba "Evolução".
  2. Ações: filtrar por período, por aparelho, alternar entre visão gráfico/tabela.
  3. Validações: papel ATLETA/RESPONSAVEL só pode consultar a própria atleta vinculada.
  4. Processamento: agrega execuções por movimento (taxa de acerto) e evolução do valor de dificuldade dominado ao longo do tempo.
  5. Resposta: gráfico de linha/barra (Recharts) + tabela detalhada exportável (V2).
  6. Erros possíveis: sem dados ainda (estado vazio orientando a registrar o primeiro treino); falha ao carregar (mensagem amigável + tentar novamente).
  7. Estado final: nenhuma alteração de dado, é uma tela somente leitura.

8. Telas

TelaPerfisObjetivoComponentes/estados principais
LoginTodosAutenticarForm, erro de credencial, loading no botão
Recuperar/Definir senhaTodosReset de senhaForm, sucesso, link expirado
Onboarding do centroGestorCriar tenant e primeiro acessoWizard 3 passos, validação por passo
DashboardTodos (conteúdo varia por papel)Visão geralCards de indicador, atalhos, estado vazio guiado
Centros (lista)Super AdminAdministrar tenantsTabela com busca/filtro/paginação, badge de status, ações (ver/editar/desativar)
Centro (detalhe/edição)Super AdminVer e editar todos os dados do tenantForm completo: nome, slug, CNPJ, tipo, grupo (matriz/filial), plano, status, contato, e-mail, endereço com busca por CEP
Usuários (lista)GestorGerenciar equipe/atletas/responsáveisTabela com filtro por papel, ações (editar/desativar/reenviar convite)
Convite/edição de usuárioGestorCriar/editar usuárioForm, seleção de papel
Turmas (lista)Gestor/ProfessorGerenciar turmasTabela/cards com busca, paginação, ação criar
Turma (edição)Gestor/ProfessorEditar turma e gerenciar atletas vinculadasForm + lista de atletas para adicionar/remover
Equipes (lista/detalhe)Gestor/ProfessorGerenciar equipes e membrosTabela/cards, gestão de membros titular/reserva, atalho para montar série da equipe
Responsáveis (lista)Gestor/ProfessorConsultar responsáveis vinculados a atletasTabela/cards com busca, paginação
Lista de espera (lista/detalhe/edição)Gestor/ProfessorGerenciar interessados aguardando vagaTabela/cards, filtro por status, form de cadastro/edição
Atletas (lista)Gestor/ProfessorGerenciar atletasTabela/cards com busca, filtro por turma, ações (ver/editar/inativar)
Atleta (perfil)Gestor/Professor/Atleta/ResponsávelVer dados, série vigente, histórico, evoluçãoAbas: Dados · Série · Treinos · Evolução
Catálogo de movimentos (lista)Todos (edição restrita)Consultar movimentosFiltro por aparelho/grupo, busca, imagem+símbolo+valor por item
Movimento (detalhe)TodosVer detalhes do movimentoImagem, símbolo, aparelho, grupo, valor, descrição
Movimento (criar/editar customizado)Gestor/ProfessorCadastrar movimento próprio do centroForm com upload de imagem
Montagem de sérieProfessorMontar/editar série da atletaLista ordenável, busca de movimento, valor total calculado
Novo treino / Registro de treinoProfessor/GestorRegistrar execução do diaChecklist por atleta/movimento, campo de observação
Treino (detalhe)Gestor/Professor/Atleta/ResponsávelConsultar um treino registradoPresença, execução por movimento (executado/não executado), observações
Treinos (histórico)Gestor/Professor/Atleta/ResponsávelConsultar treinos passadosTabela/cards, filtro por turma, paginação
Competições (lista/registro)Gestor/ProfessorCadastrar competição e resultadosForm + tabela de resultados por atleta
Evolução da atletaTodos (dados restritos ao papel)Gráfico/tabela de progressoToggle gráfico/tabela, filtro por aparelho e período
Mensagens (recebidas/enviadas)Gestor/ProfessorTrocar 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árioTodos (edição restrita a Gestor/Professor)Visualizar e gerenciar eventos relevantesComponente 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/ProfessorCadastrar evento: título, tipo, local, dia inteiro ou início/término, descriçãoForm + confirmação de exclusão
Alertas (lista)TodosConsultar alertasAbas "Recebidos" (histórico de lidos) e "Criados por mim" (Gestor/Super Admin)
Alerta (criar/editar/detalhe)Super Admin, GestorDisparar/gerenciar alerta: título, mensagem, criticidade, alvo (todos/papel), período de exibiçãoForm + seletor de alvo (todos ou papel específico) + confirmação de exclusão
Módulos por perfilSuper AdminHabilitar/desabilitar módulos por papelSeletor de papel (aba), matriz de ações (visualizar/cadastrar/editar/deletar) por módulo, salvar com feedback
LogsSuper AdminConsultar a trilha de auditoriaTabela com filtro por centro/ação/entidade/módulo, paginação
Banco de dadosSuper AdminFerramentas de manutenção do bancoApagar dados de um centro (com confirmação), recarregar catálogo oficial, backup (placeholder)
Meu perfilTodosDados pessoais, foto, endereço, senhaForm completo com upload de foto e busca de endereço por CEP
Configurações do centroGestorDados do tenant, plano (somente leitura no MVP)Form parcialmente bloqueado
404 / ErroTodosEstado de exceçãoJá 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 #E52B8F e 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 via aria-live.

10. Responsividade

FaixaComportamento
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

CamadaEscolhaMotivo
FrontendNext.js 15 + React 19 + TypeScript + TailwindJá em uso no scaffold; um único framework cobre SSR, rotas e API
BackendRoute Handlers/Server Actions do próprio Next.jsEvita um segundo serviço/deploy para um projeto deste porte
Banco de dadosPostgreSQL + Prisma ORMRelacional se encaixa bem no domínio (tenants, papéis, séries, treinos); Prisma já validado no scaffold
AutenticaçãoNextAuth (Credentials, sessão JWT)Já implementado; evita reinventar hashing/sessão
Armazenamento de arquivosCloudflare R2 ou Supabase StorageS3-compatível, custo baixo, sem egress caro (R2)
E-mail transacionalResendBoa DX com Next.js, fila própria, custo baixo em volume inicial
GráficosRechartsLeve, componível em React, suficiente para linha/barra de evolução
Hospedagem/DeployVercel (app) + Neon/Supabase (Postgres gerenciado)Deploy contínuo por PR, zero ops para o tamanho atual do projeto
Monitoramento de errosSentryPadrão de mercado, integra bem com Next.js
TestesVitest (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, @@map para nomes de tabela em snake_case, e um modelo SenhaConvite para 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 (enum DiaSemana, SEGUNDA→DOMINGO), horaInicio/horaFim (String, formato HH: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 em PlanoModulo/PerfilModulo.
  • EventoCalendario — evento do módulo Calendário: tenantId, titulo, tipo (enum TipoEventoCalendario), local?, diaInteiro, dataInicio/dataFim?, descricao?, criadoPorId. Renderizado com react-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 (enum CriticidadeAlerta: INFORMATIVO/ATENCAO/ALTA/CRITICA — cor e ícone no dashboard variam por nível), alvo (enum AlertaAlvo: TODOS ou PERFIL), perfilAlvo? (papel-alvo quando alvo = 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-lido faz upsert (idempotente).
  • AuditLog.modulo — campo adicional (Modulo?, opcional) na tabela de auditoria já existente, para permitir filtrar/consultar por módulo do sistema (enum Modulo) além do texto livre já existente em entidade. Usado inicialmente nas alterações da matriz de Módulos por perfil; demais pontos de auditoria continuam usando apenas entidade.

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étodoRotaAuthDescrição
POST/api/auth/[...nextauth]—Login/logout (NextAuth)
POST/api/onboardingPública (cria conta)Cria tenant + primeiro usuário GESTOR
GET/POST/api/tenantsSUPER_ADMINListar/criar centros
GET/PATCH/api/tenants/:idSUPER_ADMINVer/editar centro
GET/POST/api/usuariosGESTORListar/convidar usuários do tenant
PATCH/api/usuarios/:idGESTOREditar papel/ativar/desativar
GET/POST/api/turmasGESTOR, PROFESSORListar/criar turmas
GET/POST/api/atletasGESTOR, PROFESSORListar/criar atletas
GET/PATCH/api/atletas/:idGESTOR, PROFESSOR, ATLETA*, RESPONSAVEL*Ver/editar atleta (*somente a própria)
GET/api/movimentosTodosListar catálogo (filtro aparelho/grupo)
POST/api/movimentosGESTOR, PROFESSORCriar movimento customizado do tenant
GET/PUT/api/atletas/:id/series/:aparelhoGESTOR, PROFESSORVer/atualizar série vigente
GET/POST/api/treinosGESTOR, PROFESSORListar/registrar treino
GET/POST/api/competicoesGESTOR, PROFESSORListar/registrar competição e resultados
GET/api/atletas/:id/evolucaoGESTOR, PROFESSOR, ATLETA*, RESPONSAVEL*Dados agregados para gráfico/tabela
GET/POST/api/eventos-calendarioTodos (criação: GESTOR, PROFESSOR)Listar/criar evento do Calendário
GET/PATCH/DELETE/api/eventos-calendario/:idTodos leitura; GESTOR/PROFESSOR edição/exclusãoVer/editar/excluir evento
GET/POST/api/alertasSUPER_ADMIN, GESTOR (criação)Listar alertas criados pelo usuário / disparar novo alerta
GET/PATCH/DELETE/api/alertas/:idCriador do alerta (edição/exclusão); destinatário (leitura)Ver/editar/excluir alerta
GET/api/alertas/ativosTodos (autenticado, com tenant)Alertas ativos ainda não lidos pelo usuário (banner do dashboard)
POST/api/alertas/:id/marcar-lidoTodos (autenticado, com tenant)Marca o alerta como lido (idempotente); usado ao fechar o banner
GET/PUT/api/perfil-modulosSUPER_ADMINVer/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_SECRET ausente 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 AuditLog para 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

FaseEscopo
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çaHardening do isolamento de tenant, rate limiting ampliado, AuditLog, revisão LGPD
5 — TestesSuítes unit/integração/E2E da seção 16
6 — DeployAmbientes (dev/staging/produção), CI/CD, Sentry, backups do Postgres gerenciado
7 — EvoluçãoCobranç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:

  1. Migrar o schema Prisma completo da seção 13 (substituindo o User mínimo atual).
  2. Popular o seed com o catálogo oficial de movimentos FIG (aparelho, grupo, valor) usando ilustração própria.
  3. 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.