DICA

Como criar a página de validação do seu SaaS em 30 minutos

Antes de construir SaaS, valida com uma página simples. Next.js + Tally + Vercel. Sem banco, sem login, sem dashboard. Do zero ao link compartilhável em 30 min.

7 min de leitura
  • Produto
  • Dev
  • Claude Code

A maioria dos devs acha que o valor está na ideia. Mentira. Ideia sozinha não vale quase nada.

O que vale é descobrir, ANTES de codar: se alguém tem esse problema, se dói o suficiente, se já paga por alguma solução, se você consegue chegar nesse público, se existe caminho real pra vender.

O erro caro

Dev gasta 2-3 meses construindo SaaS completo (login, dashboard, banco, billing) pra descobrir no lançamento que ninguém quer. Esse trabalho todo podia virar 30 minutos de página de validação + 1 post.

A página de validação testa o desejo. Sem código de produto. Sem banco. Sem dashboard. Só promessa clara + formulário.

Se ninguém clica, ninguém comenta, ninguém entra na lista — você economizou meses.

A página que valida tem 4 elementos

Só isso. Nada mais.

  1. Headline — promessa curta da dor que o produto resolve.
  2. Sub-headline — pra quem é e como resolve (1-2 linhas).
  3. Formulário — captura nome + e-mail (no máximo).
  4. Prova social mínima — uma frase tipo "Já temos X pessoas na lista" ou "Próxima turma em [data]".

Sem features. Sem screenshots. Sem preço. Sem "saiba mais".

A stack: Next + Tally + Vercel

  • Next.js — framework. Page única estática, carrega rápido, deploy via GitHub.
  • Tally — formulário externo. Grátis sem limite de respostas, exporta CSV, integra com Notion/Slack/Email. Você cola um <script> na página e pronto.
  • Vercel — hospedagem. Free tier serve. Domínio .vercel.app ou conecta domínio próprio depois.

Zero banco, zero backend, zero código de servidor. Tudo o que você não precisa pra validar.

Setup em 6 passos

  1. 1

    Cria o repo Next com 1 comando

    No terminal:

    npx create-next-app@latest pagina-validacao --typescript --tailwind --app --no-src-dir --import-alias "@/*"
    cd pagina-validacao
    git init && git add . && git commit -m "init"

    Sobe pro GitHub. Cria repo novo no github.com/new, copia os 2 comandos de "push existing repo" e roda.

  2. 2

    Cria o formulário no Tally

    Abre tally.so, cadastra (login com Google). Cria form novo:

    • Campo 1: Nome (single-line text)
    • Campo 2: E-mail (email, required)
    • Campo 3 (opcional): Qual seu maior desafio com [problema X] hoje? (long text) — vale ouro pra entender a dor real

    Em Share → Embed, copia o trecho que começa com <script>. Guarda — vai colar na próxima etapa.

    Configura também: notificação por e-mail a cada resposta (Settings → Notifications) e webhook pro seu Slack/Discord se quiser ver em tempo real.

  3. 3

    Substitui o app/page.tsx pelo template

    Apaga o conteúdo de app/page.tsx e cola o snippet abaixo. Substitui o data-tally-src pela URL do seu form (Tally te dá ela junto do embed).

  4. 4

    Conecta o repo no Vercel

    Em vercel.com/new, login com GitHub, importa o repo. Não precisa configurar nada — Next.js + Vercel é zero-config.

    Build leva ~30s. Quando terminar, você ganha um link https://pagina-validacao-xyz.vercel.app. Esse já é o link pra compartilhar.

  5. 5

    (Opcional) Conecta domínio próprio

    Compra em registro.br (~R$40/ano) ou Hostinger/GoDaddy. No painel da Vercel: Settings → Domains → Add. Vercel mostra os 2 registros DNS (A e CNAME) — cola no painel do registrador. Propaga em ~10 min.

    Pular esse passo é OK pra validar — o link .vercel.app funciona igual.

  6. 6

    Compartilha e mede

    Posta no seu Instagram, LinkedIn, Twitter, Discord, grupos do Telegram. Pede pra galera comentar e marcar amigo que tem essa dor.

    Em 48h você sabe se a ideia tem demanda real. Métrica única: quantas pessoas se cadastraram dividido por quantas visualizaram. 5%+ é bom sinal. Menos de 1% é red flag.

Código mínimo (copia, cola, deploya)

Esse é o app/page.tsx completo. Tailwind já vem configurado no create-next-app.

app/page.tsxtsx
import Script from "next/script";

export default function Home() {
return (
  <main className="min-h-screen bg-zinc-50 text-zinc-900 flex items-center justify-center px-5 py-12">
    <div className="w-full max-w-[560px] flex flex-col items-center text-center">

      <span className="inline-flex items-center rounded-full bg-zinc-900 text-white px-3 py-1 text-[11px] font-medium uppercase tracking-wider mb-6">
        Lista de espera
      </span>

      <h1 className="text-[36px] sm:text-[44px] font-semibold leading-[1.1] tracking-[-0.025em] mb-4 [text-wrap:balance]">
        [PROMESSA — uma frase que descreve a dor resolvida]
      </h1>

      <p className="text-[16px] sm:text-[18px] leading-[1.55] text-zinc-600 mb-8 max-w-[480px] [text-wrap:pretty]">
        Pra [PERSONA] que [DOR ATUAL]. [SOLUÇÃO em 1 linha]. Entre na lista de espera pra ser avisado no lançamento.
      </p>

      <div className="w-full bg-white border border-zinc-200 rounded-2xl p-6 shadow-sm">
        <div
          data-tally-src="https://tally.so/embed/SEU-FORM-ID?alignLeft=1&hideTitle=1&transparentBackground=1&dynamicHeight=1"
          data-tally-width="100%"
          data-tally-height="320"
        />
      </div>

      <p className="text-[13px] text-zinc-500 mt-6">
        Já temos [N] pessoas na lista · próxima atualização [DATA]
      </p>

    </div>

    <Script
      src="https://tally.so/widgets/embed.js"
      strategy="afterInteractive"
    />
  </main>
);
}

E o app/layout.tsx mínimo (só pra ter title/description corretos pro SEO):

app/layout.tsxtsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
title: "[NOME DO SAAS] — entre na lista de espera",
description:
  "[PROMESSA EM 1 LINHA]. Pra [PERSONA] que [DOR]. Entre na lista pra ser avisado no lançamento.",
openGraph: {
  title: "[NOME DO SAAS] — entre na lista de espera",
  description: "[PROMESSA]. Entre na lista.",
  type: "website",
},
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
  <html lang="pt-BR">
    <body className={inter.className}>{children}</body>
  </html>
);
}

O que substituir

Os [COLCHETES] no template. São 5: nome do SaaS, promessa, persona, dor, e o ID do form do Tally. Em 5 minutos a página é sua.

Não é dev? Usa Lovable

Se você não escreve código, o caminho mais rápido é lovable.dev. Prompt tipo:

"Landing page de validação pra um SaaS chamado [X] que resolve [Y] pra [PERSONA]. Headline grande, subtitle de 2 linhas, formulário inline (eu vou colar embed do Tally depois), prova social discreta no rodapé. Visual clean, mobile-first, sem hero image."

Lovable gera, você vê o preview, ajusta o que não ficou bom no chat. Quando estiver OK, conecta domínio direto pelo painel. 15 minutos do zero ao ar — mas o repo fica preso no Lovable. Pra validar serve.

O que medir nos primeiros 7 dias

Não é vaidade. São 3 números:

  • Taxa de cadastro (cadastros ÷ visitas). 5%+ é sinal forte. 1-3% é razoável. Menos de 1% é red flag.
  • Comentários e DMs no post que divulgou. Pessoas perguntando "quando lança?" valem mais que cadastro silencioso.
  • Qualidade do campo aberto do form (a pergunta "qual seu maior desafio"). Se vier resposta detalhada e específica, você achou a dor. Se vier genérico, ainda não.

Sinal verde pra construir

Cadastros consistentes (não só do círculo próximo), pelo menos 3-5 conversas profundas no DM/WhatsApp com gente da lista, e respostas no campo aberto que confirmam a dor com exemplos concretos. Aí vale construir.

Fechamento

Validar leva 30 minutos. Construir SaaS sem validar leva 3 meses. A matemática se resolve sozinha.

Se quer o checklist que eu uso pra validar uma ideia antes de programar (perguntas pra fazer no post, pra fazer no DM, e critério de "passa/não passa"), comenta VALIDAR no meu Instagram que eu te mando.

Curtiu a dica?

Posto bastidores e mais comandos como esse no Instagram. Se for sobre o seu negócio, chama direto no WhatsApp.