amostra 05/em produção
SK Agency
Um site institucional e uma plataforma onde cada cliente acompanha o próprio contrato, do onboarding à renovação.
- Next
- Prisma
- GSAP
- Three
- Turbo
01
Contexto
A SK Agency trabalha com tecnologia e marketing. O projeto reúne o site da agência e uma plataforma em que cada cliente acompanha campanhas, relatórios, propostas, reuniões e chamados, enquanto a equipe administra tudo num painel.
Em agosto, o site acompanhou uma mudança de posicionamento: de agência de audiovisual e tráfego para software house de tecnologia e marketing.
02
Ponto de partida
O projeto começou pelo site, com uma narrativa visual em 3D, e cresceu para a operação da agência.
1
site institucional com narrativa em 3D
0
ferramentas para o cliente acompanhar o trabalho
0
pagamentos ou contratos no sistema
03
Linha do tempo
178 commits no histórico do projeto. Estes são os marcos.
14 de mai. de 2026
Site com narrativa em 3D
Motor de partículas guiado pelo scroll, sistema editorial e as primeiras páginas de cases.
16 de mai. de 2026
Contratos e integrações
Ciclo de contrato de 95 dias com pausa e renovação, e conexão OAuth com o Google Ads.
17 de mai. de 2026
O portal do cliente
Propostas com conversa entre as partes, agendamento de reuniões, chamados, painéis com dados reais de campanha e todo armazenamento de arquivos privado.
19 de mai. de 2026
Papéis e proteção
Quatro papéis com permissões distintas e limite de requisições nas rotas públicas e de autenticação.
27 de mai. de 2026
Onboarding guiado
Jornada do novo cliente em etapas, da proposta comercial ao início do contrato.
01 de jun. de 2026
Performance da home
No teste de performance, o maior elemento da home levava 21 segundos para aparecer. Imagens em WebP, vídeo próprio para o celular e carregamento sob demanda atacaram o problema.
03 de jun. de 2026
Pagamentos com Stripe
Checkout no onboarding, webhook, upgrade com cobrança proporcional e travas de segurança para o modo de produção.
15 de ago. de 2026
Novo posicionamento
Home reescrita para software house de tecnologia e marketing, com o Atlas apresentado como produto.
04
Mapa de decisões
Reconstruído a partir do histórico de commits, do README e da documentação do projeto.
01
O servidor manda no catálogo
Preços, combos e cotas são definidos no servidor e ajustáveis pelo painel. O navegador nunca informa quanto algo custa.
02
O contrato tem um ciclo
Cada contrato dura 95 dias, pode ser pausado e renovado, e começa quando o onboarding termina. O cliente vê o prazo na própria tela.
03
Permissões num lugar só
Um único arquivo diz o que cada papel pode fazer, e toda rota administrativa consulta essas regras antes de agir.
04
Tudo privado por padrão
RLS nas tabelas públicas e armazenamento de arquivos privado, com acesso por URL temporária.
05
Dados reais, não simulados
Os painéis mostram as campanhas do Google Ads sincronizadas automaticamente, com 90 dias de histórico para os filtros.
06
Pesado só onde cabe
O 3D e o vídeo do hero rodam só no computador. No celular a página carrega leve, sem abrir mão da identidade.
05
Arquitetura
As mesmas cinco camadas desta página, aplicadas ao projeto.
000 m/interface
- Site com narrativa em 3D
- Portal do cliente
- Painel administrativo
030 m/rota
- Auth.js com papel relido a cada sessão
- Limite de requisições
- OAuth protegido contra CSRF
060 m/serviço
- Permissões centralizadas por papel
- Stripe: checkout, webhook e proração
- Sincronização com o Google Ads
- E-mails com Resend
090 m/repositório
- Prisma com Postgres
- Catálogo comercial no servidor
120 m/persistência
- RLS nas tabelas públicas
- Arquivos privados por URL temporária
06
Código
Um trecho do repositório privado, só para mostrar a camada funcionando.
O que cada papel pode fazer
O middleware só pergunta se a pessoa é da equipe. Cada ação administrativa consulta a permissão específica antes de executar.
export type Role = "CEO" | "ADMIN" | "AGENT" | "CLIENT";
export const ADMIN_TIER: Role[] = ["CEO", "ADMIN", "AGENT"];
/** True iff the role is admin/agent/CEO — i.e. has access to /dashboard/admin. */
export function isAdminTier(role: Role | string | undefined | null): boolean {
return !!role && (ADMIN_TIER as string[]).includes(role);
}
/** CEO only. */
export function canManageTeam(role: Role | string | undefined | null): boolean {
return role === "CEO";
}07
Resultado
4
papéis com permissões distintas
95
dias por ciclo de contrato, com renovação
3
integrações: Stripe, Google Ads e Resend
Estado atual
Em produção em skagency.com.br.