/saas — Construtor de SaaS Full-Stack
Gatilho: /saas [ideia] ou apenas /saas (irá solicitar a ideia)
Resultado: Um SaaS completo, pronto para produção, implantado em uma URL da Vercel. Com autenticação funcional, backend real, dados ao vivo e UI bonita. Não é uma demonstração. Não é um esqueleto. É um produto real.
VISÃO GERAL DO PIPELINE
CAPTAÇÃO → PESQUISA (paralela) → PLANO → ESCLARECIMENTO → CONSTRUÇÃO → TESTE → REVISÃO → IMPLANTAÇÃO
Cada fase controla a próxima. Sem atalhos. Sem pular etapas.
FASE 1 — CAPTAÇÃO
Se o usuário executou /saas [ideia], extraia a ideia do comando.
Se executou /saas sem argumento, pergunte:
Qual é a ideia de SaaS? Descreva em 1-3 frases. Inclua:
- O que faz
- Para quem é
- Qual problema resolve
Armazene como IDEA. Confirme de volta em uma frase antes de prosseguir.
FASE 2 — PESQUISA PARALELA
Dispare duas trilhas de pesquisa simultaneamente usando a ferramenta Agent. NÃO espere uma terminar para começar a outra.
Trilha A — Inteligência de Mercado
Crie um agente general-purpose com este prompt:
Pesquise o mercado de SaaS para esta ideia: [IDEA]
Entregue um relatório estruturado cobrindo:
1. PLAYERS EXISTENTES (5-8 concorrentes)
- Nome, URL, faixas de preço, posicionamento
- O que fazem bem, o que deixam passar
- ARR estimado, se disponível
2. TAMANHO DO MERCADO E DEMANDA
- Categoria (CRM, gerenciamento de projetos, análises, etc.)
- Estimativa de tamanho do mercado
- Tendência de crescimento (crescendo/estável/declinando)
- Evidências de demanda (threads no Reddit, votos no ProductHunt, vagas de emprego)
3. REFERÊNCIAS DE PREÇO
- Freemium vs apenas pago vs trial
- Pontos de preço típicos ($/usuário/mês, fixo, baseado em uso)
- Quais modelos vencem nesta categoria
4. TABELA DE FUNCIONALIDADES
- Liste as 10 funcionalidades mais comuns entre concorrentes
- Marque quais são requisitos básicos vs diferenciais
5. ESPAÇO EM BRANCO
- O que os concorrentes NÃO estão fazendo?
- Onde os usuários reclamam? (verifique G2, Capterra, Reddit)
- Qual é a oportunidade de entrada?
Retorne markdown estruturado. Seja específico. Sem enrolação.
Trilha B — Pesquisa de Padrões Técnicos
Crie um segundo agente general-purpose:
Pesquise os padrões de implementação técnica para este tipo de SaaS: [IDEA]
Entregue:
1. PADRÕES DE MODELO DE DADOS
- Quais tabelas/entidades este tipo de aplicação normalmente precisa?
- Relacionamentos e restrições principais
- Abordagem de multi-tenancy (org_id por linha vs esquemas separados)
2. PADRÕES DE AUTENTICAÇÃO
- Este tipo de app precisa de login social? Magic link? SSO?
- Apenas convite vs cadastro aberto?
- Padrões de função (admin/membro/visualizador típico?)
3. PADRÕES DE FATURAMENTO
- Por assento, baseado em uso ou fixo?
- Estratégia de nível gratuito que funciona neste espaço?
4. NECESSIDADES DE INTEGRAÇÃO
- Com o que apps desta categoria normalmente se integram?
- Webhooks, Zapier, chaves de API?
5. RISCOS TÉCNICOS
- O que é difícil de construir nesta categoria?
- O que as equipes erram?
- Considerações de desempenho/escala
Retorne markdown estruturado. Seja específico.
Aguarde AMBAS as trilhas terminarem antes de prosseguir.
FASE 3 — PLANO DE ARQUITETURA
Usando ambos os resultados da pesquisa, produza um plano de construção estruturado. Escreva em .saas-workspace/[project-slug]/PLAN.md.
O plano deve incluir:
3.1 Definição do Produto
## Produto
Nome: [derivado da ideia, pode ser alterado]
Slogan: [uma linha]
Proposta de valor central: [uma frase]
Usuário alvo: [persona específica]
## Conjunto de Funcionalidades MVP (o que estamos construindo HOJE)
- [Funcionalidade 1] — [por que está no escopo]
- [Funcionalidade 2] — [por que está no escopo]
...
## Fora do Escopo (v1)
- [Funcionalidade] — [adiar para v2 porque...]
3.2 Modelo de Dados
Projete o esquema Postgres completo. Para cada tabela:
- Nome da tabela, propósito
- Todas as colunas com tipos, restrições, valores padrão
- Relacionamentos de chave estrangeira
- Políticas RLS necessárias
- Índices
Comece com estas tabelas obrigatórias:
-- Sempre incluir:
profiles (estende auth.users)
organizations (se multi-inquilino)
organization_members (se multi-inquilino)
subscriptions (se houver faturamento)
Depois adicione tabelas específicas do domínio para o produto.
3.3 Mapa de Rotas
Página inicial: /
Autenticação: /login /signup /auth/callback
Shell do app: /app (requer autenticação)
Funcionalidades principais: /app/[funcionalidade] (uma por funcionalidade MVP)
Configurações: /app/settings
Rotas de API: /api/... (liste cada uma)
3.4 Confirmação da Stack Tecnológica
Framework: Next.js 15 (App Router, TypeScript)
Banco: Supabase (Postgres + Auth + RLS)
Estilo: Tailwind CSS v4 + shadcn/ui
E-mail: Resend (transacional)
Implantação: Vercel
Pagamentos: Stripe (se necessário faturamento)
3.5 Ordem de Construção
Liste a sequência exata: migrações → auth → rotas de API → shell do app → funcionalidades → página inicial → templates de e-mail → testes.
FASE 4 — PERGUNTAS DE ESCLARECIMENTO
Antes de escrever uma única linha de código, identifique lacunas. Use AskUserQuestion para perguntar o seguinte (agrupe em no máximo 4 perguntas por chamada):
Rodada 1 — Escopo do Produto:
- Confirme o nome (apresente 3 opções derivadas da ideia)
- Multi-inquilino (equipes/orgs) ou contas de usuário único?
- A v1 precisa de pagamentos/faturamento, ou é gratuita enquanto constrói?
- Alguma funcionalidade específica da pesquisa que seja obrigatória vs opcional?
Rodada 2 — Design e Implantação (só pergunte se as respostas da Rodada 1 levantarem novas questões):
- Domínio? (ou use subdomínio da Vercel por enquanto)
- Alguma cor/marca preferida? (padrão: sistema verde escuro Rawgrowth)
- Endereço de e-mail do remetente para Resend?
Incorpore as respostas no PLAN.md antes de prosseguir.
FASE 5 — CONSTRUÇÃO
Configuração Pré-Construção
Carregue estas skills antes de escrever qualquer código:
frontend-theme— injeta o sistema de design completo Rawgrowthui-ux-pro-max— decisões de design, paleta, tipografia- Invoque Magic MCP (
@21st-dev/magic) para quaisquer componentes complexos
Localização do projeto: Crie em ~/saas-projects/[project-slug]/
Comando de scaffolding:
cd ~/saas-projects
npx create-next-app@latest [project-slug] \
--typescript \
--tailwind \
--eslint \
--app \
--src-dir \
--import-alias "@/*" \
--no-git
cd [project-slug]
Instalar dependências:
npm install @supabase/supabase-js @supabase/ssr \
resend \
@radix-ui/react-icons \
lucide-react \
class-variance-authority clsx tailwind-merge \
zod \
@hookform/resolvers react-hook-form
# iniciar shadcn/ui
npx shadcn@latest init --defaults
# Adicionar componentes shadcn
npx shadcn@latest add button input label card \
dropdown-menu avatar badge separator toast \
dialog sheet tabs form
Configuração Tailwind v4 — aplique os tokens do frontend-theme em src/app/globals.css.
5.1 Banco de Dados e Migrações
Use a skill add-migration para cada migração.
Migração 1: Esquema principal
-- Habilitar RLS em todas as tabelas voltadas ao usuário
-- profiles: estende auth.users
CREATE TABLE profiles (
id UUID REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
email TEXT NOT NULL,
full_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Usuários podem ver seu próprio perfil"
ON profiles FOR SELECT USING (auth.uid() = id);
CREATE POLICY "Usuários podem atualizar seu próprio perfil"
ON profiles FOR UPDATE USING (auth.uid() = id);
-- Criar perfil automaticamente no cadastro
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, email, full_name, avatar_url)
VALUES (
NEW.id,
NEW.email,
NEW.raw_user_meta_data->>'full_name',
NEW.raw_user_meta_data->>'avatar_url'
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
Migração 2: Organizações (se multi-inquilino)
CREATE TABLE organizations (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
name TEXT NOT NULL,
slug TEXT UNIQUE NOT NULL,
owner_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,
plan TEXT DEFAULT 'free',
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE organization_members (
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
org_id UUID REFERENCES organizations(id) ON DELETE CASCADE NOT NULL,
user_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,
role TEXT NOT NULL DEFAULT 'member' CHECK (role IN ('owner', 'admin', 'member')),
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(org_id, user_id)
);
ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;
ALTER TABLE organization_members ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Membros podem ver sua organização"
ON organizations FOR SELECT
USING (id IN (
SELECT org_id FROM organization_members WHERE user_id = auth.uid()
));
CREATE POLICY "Membros podem ver associação à organização"
ON organization_members FOR SELECT
USING (org_id IN (
SELECT org_id FROM organization_members WHERE user_id = auth.uid()
));
Migração 3+: Tabelas de domínio — crie tabelas específicas do produto conforme o modelo de dados no PLAN.md. Aplique RLS a cada tabela.
5.2 Configuração do Cliente Supabase
src/lib/supabase/client.ts:
import { createBrowserClient } from '@supabase/ssr'
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
src/lib/supabase/server.ts:
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
export async function createClient() {
const cookieStore = await cookies()
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() { return cookieStore.getAll() },
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {}
},
},
}
)
}
src/middleware.ts — proteja todas as rotas /app/*, redirecione usuários não autenticados para /login.
5.3 Páginas de Autenticação
Construa /login e /signup como páginas completas (não modais). Aplique frontend-theme:
- Fundo escuro (#060B08)
- Cartão centralizado com borda (rgba(255,255,255,0.06))
- Botões CTA verdes (#0CBF6A)
- Campos de e-mail + senha (+ login social se configurado)
- Link "Esqueceu a senha"
- Sem emojis. Limpo, premium, minimalista.
src/app/(auth)/login/page.tsx — formulário de login com Supabase Auth
src/app/(auth)/signup/page.tsx — formulário de cadastro com fluxo de confirmação de e-mail
src/app/auth/callback/route.ts — manipulador de callback OAuth/magic link
Fluxo de confirmação de e-mail:
- Ao cadastrar → Supabase envia e-mail de confirmação (via Resend SMTP)
- Rota de callback troca código por sessão
- Redirecionar para
/app/dashboardem caso de sucesso
5.4 Shell do App
src/app/(app)/layout.tsx — layout autenticado com:
- Barra lateral (recolhível em mobile)
- Navegação superior com avatar do usuário + menu suspenso (perfil, configurações, sair)
- Breadcrumbs
- Saída de notificações Toast
Itens da barra lateral derivados do mapa de rotas no PLAN.md.
Use Magic MCP para buscar um componente de barra lateral: pesquise por "dashboard sidebar dark" e adapte aos tokens do frontend-theme.
5.5 Páginas de Funcionalidades Principais
Para cada funcionalidade no conjunto MVP (do PLAN.md):
- Primeiro o design — consulte Magic MCP para padrões de componentes relevantes
- Camada de dados — componentes servidor buscam do Supabase diretamente
- Mutações — Server Actions com validação Zod
- Estados de erro — todo formulário tem erros de validação, estados de carregamento, estados vazios
- Sem tipos
any— gere tipos TypeScript a partir do esquema Supabase
Padrão para componente servidor de busca de dados:
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
export default async function DashboardPage() {
const supabase = await createClient()
const { data: { session } } = await supabase.auth.getSession()
if (!session) {
redirect('/login')
}
const { data: profile } = await supabase
.from('profiles')
.select('*')
.eq('id', session.user.id)
.single()
return (
<div>
<h1>Bem-vindo, {profile?.full_name || 'Usuário'}!</h1>
</div>
)
}