Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Saúde em equilíbrio com o seu futuro. Painel de gestão das academias do ecossistema Synse — alunos, planos, mensalidades, treinos, check-in e pagamentos em um único produto. O projeto sobe sem nenhuma configuração. Sem credenciais de Supabase ele entra em modo de demonstração, com uma academia completa em memória: 520 alunos, 12 meses de mensalidades, check-ins, treinos e avaliações. Requer Node 22 ou mais recente, disponível em nodejs.org. Abra http://localhost:3000 e escolha um perfil na tela de login.查看完整 README ↗
Saúde em equilíbrio com o seu futuro.
Painel de gestão das academias do ecossistema Synse — alunos, planos, mensalidades, treinos, check-in e pagamentos em um único produto.
O projeto sobe sem nenhuma configuração. Sem credenciais de Supabase ele entra em modo de demonstração, com uma academia completa em memória: 520 alunos, 12 meses de mensalidades, check-ins, treinos e avaliações.
Requer Node 22 ou mais recente, disponível em nodejs.org.
git clone -b claude/kind-goldberg-c16nsx https://github.com/BrazZ7/SynseHUB.git
cd SynseHUB
npm install
npm run dev
Abra http://localhost:3000 e escolha um perfil na tela de login.
docker build -t synsehub .
docker run -p 3000:3000 synsehub
Ou, para publicar o seu próprio repositório: em vercel.com → Add New → Project,
importe BrazZ7/SynseHUB e selecione o branch claude/kind-goldberg-c16nsx.
O Next.js é detectado automaticamente e nenhuma variável de ambiente é
necessária para o modo de demonstração.
| Perfil | O que vale a pena olhar |
|---|---|
| Emerson Braz (Proprietário) | Dashboard, financeiro, inadimplentes, Synse Pay |
| Rafael Nunes (Professor) | O mesmo dashboard sem receita nem inadimplência — o RBAC em ação |
| Lucas Ferraz (Recepção) | Check-in: busque um aluno e registre a presença |
| Aluno Synse App | A experiência do aluno: treino do dia, check-in, progresso, PIX |
| Synse Plataforma (Super admin) | /synse-admin: GMV, comissão e organizações |
Vale testar também: cadastrar um aluno em Alunos → Novo aluno (ele nasce com Synse ID e primeira mensalidade), dar baixa numa cobrança em Inadimplentes → Cobrar → Registrar pagamento e ver o painel recalcular, e reduzir a janela do navegador até a largura de um celular.
O Synse é um ecossistema de saúde, fitness e bem-estar operando em B2B2C: a academia contrata a plataforma, e os alunos dela ganham acesso gratuito ao app. A Synse também pode vender diretamente a esses usuários.
| Produto | O que é | Estado |
|---|---|---|
| SynseHub | Painel administrativo da academia | Fase 1 implementada |
| Synse App | Área do aluno (PWA responsiva) | Primeira versão |
| Synse Pay | Cobranças, split e conciliação | Arquitetura + provedor simulado |
| Synse+ | Assinatura premium do consumidor | Página de venda |
| Synse Pro | Profissionais independentes | Papel e permissões prontos |
| Synse Market / AI / Corporate | Marketplace, IA e corporativo | Arquitetura preparada |
Cada pessoa tem um identificador vitalício no formato SYN-XXXXXXXX
(Crockford base32, sem I, L, O e U). Ele é não sequencial por decisão de
segurança: um ID não permite inferir outro nem estimar o tamanho da base.
A conta sobrevive ao vínculo com a academia. Um aluno que treina dois anos na Academia Alpha e sai continua com a conta Synse, o histórico e o progresso — respeitando consentimentos e regras de acesso.
src/
app/
(auth)/ Login e escolha de perfil
(hub)/ SynseHub — painel da academia
(student)/ Synse App — experiência do aluno
synse-admin/ Painel da plataforma (SUPER_ADMIN)
api/ Webhooks e health check
components/
ui/ Primitivas (Radix + CVA), estilo shadcn/ui
synse/ Componentes da marca: MetricCard, DataTable, ProgressRing…
charts/ Gráficos Recharts com paleta validada
features/ Um módulo por domínio: actions, services e telas
auth/ students/ payments/ checkin/ workouts/ dashboard/ organizations/
lib/
auth/ Sessão, guardas de rota e server actions de acesso
database/ Data sources (demo e Supabase) + clientes
payments/ Interface PaymentProvider e adapters
permissions/ RBAC e guarda de servidor
validations/ Schemas Zod
db/migrations/ SQL versionado: schema, índices, RLS
types/ Modelo de domínio
config/ Configuração pública e navegação
Multi-tenancy em duas camadas. Toda consulta filtra por organization_id
explicitamente, e o Postgres aplica Row Level Security por cima. A redundância é
intencional: se uma policy for afrouxada por engano, a aplicação continua isolada.
Autorização no servidor. O front-end usa can() apenas para esconder UI.
Cada server action passa por requirePermission() antes de tocar em dados.
Esconder um botão nunca é o controle de acesso.
Gateway atrás de uma interface. Nenhum código específico de gateway existe fora
de lib/payments/providers/. O resto do sistema conhece apenas PaymentProvider,
e isso já se provou na prática: o Asaas foi removido sem que uma linha de regra de
negócio, tela ou migration precisasse mudar.
Dinheiro só muda por confirmação externa. O status de um pagamento muda a partir de um webhook validado ou de uma consulta ao provedor. Nunca a partir do navegador.
Lógica fora dos componentes. Componentes React renderizam. Regra de negócio vive
em features/*/service.ts, acesso a dados em data sources, validação em schemas Zod.
As APIs já estão desenhadas para servir também um app React Native no futuro.
Next.js 15 (App Router) · React 19 · TypeScript strict · Tailwind CSS 3 Radix UI · Lucide Icons · Recharts · Zod · React Hook Form · TanStack Query Supabase (Postgres, Auth, Storage, RLS)
git clone https://github.com/BrazZ7/SynseHUB.git
cd SynseHUB
npm install
cp .env.example .env.local
npm run dev
Abra http://localhost:3000.
Sem nenhuma configuração o projeto já sobe funcionando. Sem credenciais de Supabase, o SynseHub usa um data source em memória com uma academia completa: 520 alunos, 12 meses de mensalidades, check-ins, treinos e avaliações. O dataset é determinístico — os mesmos números em qualquer máquina.
Na tela de login você escolhe o perfil com que quer entrar:
| Perfil | O que enxerga |
|---|---|
| Emerson Braz — Proprietário | Tudo na organização |
| Marina Duarte — Gerente | Operação, alunos e financeiro |
| Rafael Nunes — Professor | Treinos, avaliações e alunos; sem financeiro |
| Lucas Ferraz — Recepção | Check-in, matrículas e cobranças |
| Aluno Synse App | A experiência do aluno |
| Synse Plataforma — Super admin | Todas as organizações e o GMV |
Não existe senha em modo demonstração: a persona escolhida vira uma sessão em cookie, e as permissões de cada papel valem normalmente — inclusive as restrições. O modo só existe quando não há Supabase configurado.
O dataset base é determinístico e nunca é alterado: ele é reconstruído idêntico em qualquer processo. O que o visitante muda — matricular um aluno, dar baixa numa cobrança, registrar presença — vira uma entrada num diário guardado em cookie, reaplicada sobre o dataset base a cada leitura.
Essa separação resolve dois problemas de uma vez:
O diário guarda no máximo 40 alterações e 3,5 KB. Ao estourar, as mais antigas saem. O botão Reiniciar demonstração, no topo do painel, apaga o diário e devolve tudo ao estado inicial.
Copie .env.example para .env.local. Nenhum segredo é versionado.
| Variável | Obrigatória | Descrição |
|---|---|---|
NEXT_PUBLIC_APP_URL | sim | URL pública (links de cobrança, webhooks) |
NEXT_PUBLIC_SYNSE_ENV | sim | development · staging · production |
NEXT_PUBLIC_SUPABASE_URL | não¹ | URL do projeto Supabase |
NEXT_PUBLIC_SUPABASE_ANON_KEY | não¹ | Chave anônima (sujeita à RLS) |
SUPABASE_SERVICE_ROLE_KEY | não² | Somente servidor. Ignora RLS |
PAYMENT_PROVIDER | sim | mock — é o único hoje. Nome desconhecido cai no simulado e aparece em /api/health?deep=1 |
SYNSE_DEFAULT_PLATFORM_FEE_PERCENTAGE | não | Comissão padrão (o valor efetivo vem do banco) |
¹ Sem as duas, a aplicação entra em modo demonstração. ² Necessária para processar webhooks e rodar o seed.
Arquivos versionados em src/db/migrations, aplicados em ordem:
| Arquivo | Conteúdo |
|---|---|
0001_core.sql | Perfis, organizações, equipe, planos, alunos, matrículas |
0002_payments.sql | Contas, cobranças, pagamentos, split, webhooks, régua |
0003_training_health_content.sql | Check-in, treinos, avaliações, nutrição, conteúdo, CRM, LGPD |
0004_rls.sql | Row Level Security em todas as tabelas |
0005_student_profile_visibility.sql | Equipe lê o perfil de quem tem matrícula |
0006_unique_profile_email.sql | E-mail único por perfil |
0007_organization_signup.sql | Cadastro de academia pela própria dona |
0008_rls_performance.sql | Políticas em forma de conjunto: 997 ms → 23 ms |
0009_payment_marketplace.sql | Subconta por academia e segredo do provedor |
0010_organization_fiscal_address.sql | Dados fiscais exigidos pelo provedor |
0011_self_signup.sql | Código de convite, entrada do aluno, tipo da organização |
0012_notification_events.sql | Gatilhos que enchem o sino |
0013_synse_solo.sql | Organização reservada: treinar sem academia vinculada |
0014_baseline_experience.sql | Plano da conta, desafios base, progresso e medalhas |
0015_professional_unlock.sql | Perfil profissional como assinatura, não como tipo de cadastro |
0016_synse_run.sql | SynseRun: atividades, rota, parciais e recordes |
npm run db:migrate # lista as migrations e como aplicá-las
npm run db:migrate -- --print > db.sql # SQL consolidado
# Aplicar via Supabase CLI
supabase link --project-ref <project-ref>
supabase db push
npm run db:seed
Cria uma academia, seis profissionais, cinco planos, 534 alunos com mensalidades, check-ins e avaliações — volume suficiente para as consultas revelarem o que uma academia de vinte alunos esconde.
Nenhuma senha é gerada. As contas nascem no Supabase Auth com e-mail confirmado e sem senha — o acesso previsto é por link no e-mail. Não existe credencial fixa no repositório nem no banco.
Enquanto não houver SMTP próprio, o link do e-mail não chega a lugar nenhum. Para entrar sem depender de e-mail:
npm run db:set-password -- --gerar # sorteia a senha e mostra uma vez
npm run db:set-password # ou digite a sua
npm run db:set-password -- [email protected] # em outra conta
O script exige SUPABASE_SERVICE_ROLE_KEY no .env.local, mostra o estado da
conta (e-mail confirmado, provedores, último acesso) e testa o login de
verdade antes de dizer que deu certo. Se a tela recusar depois de o teste
passar, o problema não é a senha.
A senha nunca vai por argumento — isso a gravaria no histórico do shell.
| Papel | Escopo |
|---|---|
SUPER_ADMIN | Plataforma Synse: organizações, GMV, assinaturas, webhooks |
OWNER | Controle completo da sua organização |
MANAGER | Administrativo, sem alterar configurações nem estornar |
RECEPTIONIST | Alunos, pagamentos, check-in e agenda |
TRAINER | Treinos, avaliações e alunos atribuídos |
NUTRITIONIST | Área nutricional dos pacientes autorizados |
PROFESSIONAL | Profissional independente (Synse Pro) |
STUDENT | Synse App |
A matriz completa está em src/lib/permissions/permissions.ts e é visível na
interface em Configurações → Permissões.
Três camadas independentes protegem cada acesso:
requireHubSession(permission) barra a rota antes de renderizar.requirePermission(session, permission) barra cada server action.// Todo o sistema depende apenas disto:
const provider = getPaymentProvider()
await provider.createPix({ ... })
Para adicionar um gateway, implemente PaymentProvider
(src/lib/payments/provider.ts) e registre na fábrica em
src/lib/payments/index.ts. Nenhuma tela muda.
A comissão da Synse nunca está fixa no código. Ela vem de
organization_billing_settings (percentual, taxa fixa e quem absorve a tarifa do
provedor) e é alterável apenas pela plataforma — a própria academia não edita a
própria comissão. O cálculo vive em src/lib/payments/split.ts e garante que a
soma feche com o valor cobrado, sem centavo perdido.
Sem provedor, não há rota de webhook — ela nasce junto com o adapter. O mecanismo que recebe o evento continua de pé e vale para quem vier:
webhook_events tem UNIQUE (provider, event_id).
O mesmo evento reenviado falha no INSERT, é reconhecido e ignorado. Não existe
liquidação em duplicidade.Não há provedor de pagamento conectado. O Asaas foi removido por causa da taxa e o substituto ainda não foi escolhido, então o único provedor é o simulado: nenhum centavo se move, em nenhum ambiente. O Synse Pay — o marketplace em que a academia cobra o aluno e a plataforma retém a comissão — está engavetado junto, e as telas dizem isso em vez de fingir que operam.
Quem for ligar o próximo provedor escreve um adapter em lib/payments/providers/
e uma rota de webhook. O que a interface exige é o que restringe a escolha: além de
PIX, boleto, cartão e assinatura recorrente, ela pede createPaymentAccount
(subconta por academia) e configureSplit. Provedor sem marketplace atende a
assinatura do Synse+ e não atende o Synse Pay.
Dados de saúde (avaliações físicas e planos nutricionais) recebem tratamento próprio:
author_staff_id é NOT NULL com ON DELETE RESTRICT. O sistema não emite
prescrição clínica nem interpreta medidas automaticamente.INSERT WITH CHECK (false) na chave anônima).npm run dev # desenvolvimento
npm run build # build de produção
npm run start # servidor de produção
npm run lint # ESLint
npm run typecheck # TypeScript strict
npm run format # Prettier
npm run db:migrate # migrations
npm run db:seed # dados de demonstração
Os tokens vivem em src/app/globals.css e são consumidos pelo Tailwind. O tema
escuro redefine apenas as variáveis — nenhuma classe de componente muda.
| Token | Claro | Escuro |
|---|---|---|
--synse-bg | #F5FAF8 | #041D1B |
--synse-surface | #FFFFFF | #082925 |
--synse-primary | #00A98F | #17C4A5 |
--synse-cyan | #22C7D8 | #35D6E6 |
--synse-text | #102B29 | #E6F5F1 |
O gradiente da marca (#00A98F → #22C7D8) é reservado para áreas estratégicas:
logo, CTA principal, indicadores de progresso e banners.
As paletas dos gráficos foram validadas para banda de luminosidade, piso de
croma, separação sob daltonismo (protanopia, deuteranopia, tritanopia) e contraste
contra a superfície do card — nos dois temas, com passos próprios em cada um.
Os valores estão em src/components/synse/charts/chart-theme.ts.
O SynseHub é executivo; o Synse App é inspiracional. Ambos pertencem visivelmente à mesma marca.
Autenticação · Multi-tenancy com RLS · Layout e navegação por papel · Dashboard com métricas derivadas · Gestão de alunos com filtros e paginação · Perfil do aluno em abas · Planos · Mensalidades · Financeiro · Inadimplentes com régua · Synse Pay simulado · Check-in por QR Code e recepção · Treinos · Synse App · Painel da plataforma · Landing page
Integração real de pagamento · Webhooks em produção · Split ao vivo · Assinaturas recorrentes · Régua automatizada com disparo · Avaliações com registro pelo profissional · Biblioteca de conteúdo · Receitas · Programas Synse 21/30/60/90 · Synse+
Nutrição profissional · Synse Pro · Gamificação e desafios · CRM avançado · Marketplace · Wearables · Synse AI
Synse AI não é construída agora, mas a arquitetura já a acomoda: ela responderá apenas sobre dados que o usuário autorizou e não substitui diagnóstico médico.
npm test # tudo
npm run test:unit # lógica pura, sem banco
npm run test:db # RLS e schema, exige PostgreSQL
Os testes de banco constroem o schema a partir das migrations reais — não há schema duplicado no diretório de testes, porque um schema paralelo divergiria justamente nos detalhes que os testes existem para proteger. Sem PostgreSQL disponível eles pulam com aviso, e a suíte de lógica pura continua rodando.
Para rodar a suíte completa, aponte TEST_DATABASE_URL para um banco vazio:
TEST_DATABASE_URL=postgresql://postgres@localhost:5432/synse_test npm run test:db
O que a suíte cobre, e por quê:
| Arquivo | Protege |
|---|---|
unit/split | o cálculo do dinheiro: soma exata, arredondamento, as três estratégias de tarifa |
unit/permissions | quem enxerga o quê, incluindo o professor que não vê o financeiro |
db/rls | isolamento entre academias, acesso anônimo, nome dos alunos visível para a equipe |
db/schema | RLS ligada em toda tabela, e-mail único, formato do Synse ID, comissão vinda do banco |
db/signup | cadastro de academia: anônimo recusado, duplicidade recusada, isolamento preservado |
db/rls-performance | a forma do plano de execução, para a RLS não voltar a ser avaliada linha a linha |
Cada teste de banco corresponde a uma falha que já aconteceu. O de desempenho verifica o plano, não o relógio: o que importa é a política ser avaliada uma vez por consulta, e não o número de milissegundos numa máquina específica.
Credenciais a rotacionar, ambiente de desenvolvimento separado, plano da Vercel
e a verificação do Synse Pay ponta a ponta estão em
docs/pre-producao.md, e o roteiro para publicar nas
lojas — do Supabase ao envio — em
docs/publicar-passo-a-passo.md.
Durante a construção é comum
adiar esses itens — a lista existe para que adiar não vire esquecer.
Honestidade sobre o estado atual, revisada em 12/09/2026.
consents
existe desde a 0003 e não é lida nem escrita por lugar nenhum. É a única tela
do produto que afirma algo falso sobre dado do usuário, e por ser matéria de
LGPD deveria sair ou virar verdade antes de qualquer cliente./workouts é somente leitura. É a lacuna mais cara do produto — o gatilho de
"novo treino disponível" nunca dispara porque nada atribui treino.createPlan existe no data source e não
tem tela nem ação.public. Num PostgreSQL fora do Supabase é preciso
conceder na mão.Disciplina hoje. Liberdade sempre.
Saúde é a base de tudo.