2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00
2026-10-02 21:36:17 -03:00

Convite Safari 🦁

Convite digital de aniversário com confirmação de presença (RSVP) e área do organizador.

  • Convidados acessam o convite pelo link /r/<token> e confirmam a presença de cada pessoa.
  • Organizador acessa /admin com senha, cadastra eventos e convites, compartilha os links (copiar / WhatsApp) e acompanha as respostas.

Stack: Next.js 16 (App Router) · React 19 · TypeScript · Tailwind CSS 4 · PostgreSQL 17 · Drizzle ORM · Docker Compose


Estrutura

src/
  app/
    page.tsx                 Página inicial pública (neutra)
    r/[token]/               Página do convite + Server Action do RSVP
    admin/login/             Login do organizador
    admin/(painel)/          Área do organizador (eventos e convites)
    admin/actions.ts         Server Actions do organizador
  components/
    invitation/              Componentes do convite
    admin/                   Formulários e componentes do organizador
  db/
    schema.ts                Tabelas (events, invitations, guests)
    index.ts                 Conexão com o Postgres
    seed.ts                  Dados de exemplo (convites abc123 e xyz789)
  lib/
    auth.ts                  Sessão do organizador (cookie assinado)
    invitation.ts            Consultas do convite público
    organizer.ts             Consultas da área do organizador
drizzle/                     Migrations SQL geradas pelo drizzle-kit
scripts/migrate.ts           Aplica as migrations (usado no container)
Dockerfile                   Imagem de produção (Next standalone)
compose.yml                  App + Postgres

Variáveis de ambiente

Copie .env.example para .env e preencha:

Variável Descrição
POSTGRES_DB Nome do banco criado pelo compose (padrão convite)
POSTGRES_USER Usuário do banco (padrão convite)
POSTGRES_PASSWORD Senha do banco. Use só letras e números (ela entra na URL de conexão)
DATABASE_URL Conexão usada fora do compose (npm run dev, db:migrate, db:seed). No compose é sobrescrita automaticamente para o serviço db
APP_PORT Porta publicada no servidor (padrão 3000)
ORGANIZER_PASSWORD Senha de acesso ao /admin
SESSION_SECRET Chave para assinar o cookie de sessão (mínimo 32 caracteres)
COOKIE_SECURE true quando servido via HTTPS (Cloudflare); false para acesso direto por http://IP

Para gerar o SESSION_SECRET:

node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"

⚠️ Com COOKIE_SECURE=true o login não funciona em HTTP puro (ex.: http://192.168.18.97:3000). Só mude para true quando o acesso for pelo domínio HTTPS do Cloudflare.


Deploy no servidor (Docker Compose)

Pré-requisitos

  • Docker com o plugin Compose (docker compose version)
  • Acesso à internet durante o build (o next build baixa as fontes do Google)

1. Copiar o projeto para o servidor

Copie a pasta do projeto (sem node_modules, .next e dist) para o servidor, por exemplo:

rsync -av --exclude node_modules --exclude .next --exclude dist ./ usuario@192.168.18.97:/opt/convite/

2. Configurar o .env

No servidor, dentro da pasta do projeto:

cp .env.example .env
nano .env

Preencha POSTGRES_PASSWORD, ORGANIZER_PASSWORD e SESSION_SECRET. Deixe COOKIE_SECURE=false enquanto o acesso for por IP.

3. Subir

docker compose up -d --build

O que acontece:

  1. O Postgres sobe e o app espera ele ficar saudável (healthcheck).
  2. O container do app aplica as migrations pendentes (drizzle/) automaticamente.
  3. O servidor Next sobe na porta APP_PORT (padrão 3000).

Acompanhe os logs:

docker compose logs -f app

Deve aparecer Migrations aplicadas. seguido da inicialização do Next.

4. Primeiro acesso

  1. Abra http://192.168.18.97:3000/admin e entre com a ORGANIZER_PASSWORD.
  2. Cadastre o evento e os convites.
  3. Use Copiar link ou WhatsApp para enviar cada convite.

O banco começa vazio. Se quiser os convites de exemplo da POC, veja Seed.


Atualizar a aplicação

Depois de copiar a nova versão do código para o servidor:

docker compose up -d --build app

As migrations novas são aplicadas na subida. Os dados do banco ficam no volume pgdata e não são perdidos ao recriar os containers.

Para desligar a migration automática, defina RUN_MIGRATIONS=false no .env.


Publicação via Cloudflare

Quando o Cloudflare passar a apontar para o servidor (igual às outras aplicações):

  1. Aponte o domínio/túnel para a porta APP_PORT do servidor.

  2. No .env, altere COOKIE_SECURE=true.

  3. Recrie o app para aplicar:

    docker compose up -d app
    

Backup e restauração do banco

Backup:

docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > backup-$(date +%F).sql

Restauração (em um banco vazio):

docker compose exec -T db sh -c 'psql -U "$POSTGRES_USER" "$POSTGRES_DB"' < backup-AAAA-MM-DD.sql

⚠️ docker compose down -v apaga o volume do banco. Use apenas docker compose down para parar os serviços.


Comandos úteis

Comando O que faz
docker compose ps Status dos containers
docker compose logs -f app Logs do app
docker compose restart app Reinicia o app
docker compose down Para tudo (mantém os dados)
docker compose exec db sh -c 'psql -U "$POSTGRES_USER" "$POSTGRES_DB"' Console SQL do banco

Desenvolvimento local

Requer Node.js 20.9+ e um Postgres acessível (pode ser só o serviço db do compose, liberando a porta 127.0.0.1:5432 no compose.yml).

npm install
cp .env.example .env      # ajuste DATABASE_URL
npm run db:migrate        # cria as tabelas
npm run db:seed           # opcional: convites de exemplo
npm run dev

Acesse http://localhost:3000. Para abrir pela rede local (ex.: celular), o IP precisa estar em allowedDevOrigins no next.config.ts.

Scripts do banco

Script O que faz
npm run db:generate Gera uma nova migration após alterar src/db/schema.ts
npm run db:migrate Aplica as migrations no banco do DATABASE_URL
npm run db:seed Cria os convites de exemplo (abc123, xyz789)
npm run db:studio Abre o Drizzle Studio para ver/editar os dados

Seed (dados de exemplo)

O seed não faz parte da imagem Docker. Para rodá-lo contra o banco do compose, libere a porta do Postgres em 127.0.0.1:5432 no compose.yml e, na máquina com o código e as dependências instaladas:

npm run db:seed

Problemas comuns

Sintoma Causa provável
Login do /admin volta para a tela de login COOKIE_SECURE=true com acesso por HTTP — use false
SESSION_SECRET não definida nos logs Variável vazia ou com menos de 32 caracteres
defina POSTGRES_PASSWORD no .env ao subir POSTGRES_PASSWORD ausente no .env
Erro de autenticação no Postgres após trocar a senha A senha só é aplicada na primeira criação do volume; altere no banco ou recrie o volume (apaga os dados)
Página em branco no npm run dev acessando por IP IP ausente em allowedDevOrigins no next.config.ts
Description
No description provided
Readme 486 KiB
Languages
TypeScript 94.7%
Python 2.6%
CSS 1.3%
Dockerfile 1.1%
JavaScript 0.3%