EA Profissional
Site institucional, agendamento online e loja em um só produto. A regra que impede dois clientes de reservarem o mesmo horário não vive no código — vive no banco.
- Cliente
- EA Profissional
- Segmento
- Estética e beleza profissional
- Local
- Itabuna, Bahia
- Escopo
- Construção e operação contínua
- Estado
- Construído · aguardando publicação
- modelos de dados
- 34
- fases entregues
- 5 / 7
- tabelas com RLS
- 100%
- sobreposições no teste de concorrência
- 0
Uma clínica de estética vive da agenda.
Um horário vendido duas vezes não é um erro de sistema: é um cliente que chega e não é atendido, uma profissional que precisa escolher quem dispensar, e uma reputação que leva meses para recuperar em uma cidade onde todo mundo se conhece.
E o negócio não cabia em um produto só. Precisava apresentar procedimentos com credibilidade, receber agendamento sem depender de troca de mensagens, e vender produto. Normalmente isso vira três ferramentas que não conversam entre si, três mensalidades e três lugares para o dado ficar desatualizado.
Verificar antes de gravar não é uma trava.
O caminho óbvio é consultar a disponibilidade no código antes de salvar. Funciona no teste, com uma pessoa por vez, e falha em produção no primeiro sábado cheio.
Duas requisições simultâneas leem a agenda no mesmo instante. As duas veem o horário livre. As duas gravam.
Um índice único em (profissional, início) impede dois agendamentos com o mesmo horário de início. Não impede sobreposição parcial: 10:00–13:00 contra 11:00–12:00 passa.
Numa constraint de exclusão do Postgres. O Prisma não sabe expressá-la, então ela entra por migração SQL escrita à mão.
ALTER TABLE appointments
ADD CONSTRAINT appointments_no_overlap
EXCLUDE USING gist (
"professionalId" WITH =,
tstzrange("startsAt", "endsAt", '[)') WITH &&
)
WHERE (status IN ('PENDING', 'CONFIRMED'));Intervalo semiaberto
O '[)' faz um atendimento que termina às 10:00 não conflitar com outro que começa às 10:00. Mesma semântica do motor de disponibilidade, para os dois nunca discordarem.
Constraint parcial
O WHERE deixa só agendamentos vivos ocupando a agenda. Cancelado e não comparecido liberam o horário sozinhos, sem rotina de limpeza.
Reserva temporária
A mesma proteção cobre a reserva que segura o horário enquanto o cliente preenche os dados — com índice de expiração, consultado a cada cálculo de disponibilidade.
A validação em código continua lá, como primeira linha de defesa e para dar uma mensagem decente ao usuário. Mas ela deixou de ser a última. O banco recusa a gravação mesmo que tudo acima dele falhe.
O banco fechado por padrão.
Row Level Security ativo nas 34 tabelas, fechando acesso direto ao banco. Um script audita e lista qualquer tabela que tenha escapado.
As variáveis de ambiente passam por validação de esquema na subida. Configuração inválida derruba o build — não a produção.
Um script dispara reservas concorrentes contra o banco real e verifica que só uma sobrevive. A garantia é testada, não assumida.
Ordenado por conversão, não por módulo.
As fases não seguem a ordem em que o software fica pronto. Seguem a ordem em que passam a dar retorno.
- 00
Fundação
Design system, modelo de dados, componentes base, deploy.
Entregue - 01
Institucional
Procedimentos, resultados e SEO local.
Entregue - 02
Agendamento
Fluxo completo de reserva online.
Entregue - 03
Loja
Catálogo em vitrine, com venda pelo WhatsApp.
Entregue - 04
Checkout
Carrinho, pagamento e frete.
Roadmap - 05
Painel
Agenda, horários, procedimentos, produtos, estoque e avaliações.
Entregue - 06
Área profissional
B2B, curso e quiz capilar.
Roadmap
A fase 3 ficou pronta em modo vitrine, com venda pelo WhatsApp, antes de o checkout existir. Ter o que vender antes de ter carrinho encurta o caminho até a primeira receita.
- Next.js 15
- React 19
- TypeScript estrito
- Tailwind CSS
- Postgres
- Prisma
- Row Level Security
- Migrações SQL à mão
- Vitest
- Playwright
- Validação de esquema com Zod
- Vercel
- Deploy contínuo
- Monitoramento
O projeto não termina na entrega.
As fases 4 e 6 seguem no roadmap e a publicação está a caminho. O contrato é de operação contínua, não de entrega única: quando o site subir, ele já nasce monitorado, atualizado e medido — e continua recebendo melhoria sem novo orçamento a cada ajuste.