Skip to content

Repository files navigation

Araújo Personal Trainer — Site

Site oficial do Araújo Personal Trainer (consultoria online e presencial de treino e nutrição — bodybuilding e estética corporal).

  • Frontend: React 18 + Vite 6 + TailwindCSS 3 (design tokens em tailwind.config.js)
  • Formulário multi-etapas: 6 passos com barra de progresso, validação campo a campo e persistência em sessionStorage
  • Backend: funções serverless (/api/*) que gravam as solicitações num Google Sheets e disparam e-mail de notificação (Resend)
  • Fotos: compressão no client (browser-image-compression) + upload para Supabase Storage; só a URL vai pra planilha/e-mail

Decisão de stack: React + Vite, e não Next.js, porque o site é um funil essencialmente cliente (brochura + formulário pesado de interação no browser). As meta/OG tags são resolvidas no index.html + react-helmet-async, e o backend vira funções serverless junto do mesmo repositório — SSR não agregaria valor aqui e adicionaria complexidade desnecessária.


1) Rodando localmente

npm install
npm run dev

Isso sobe duas coisas ao mesmo tempo:

Serviço Porta O que é
Vite (front) http://localhost:5173 o site
API Node (dev) http://localhost:8787 /api/* (proxy automático do Vite)

O backend local (server/index.mjs) e as funções de produção (api/) compartilham a MESMA lógica em server/lib/. Ou seja: tudo que funciona local funciona na Vercel.

Sem o .env preenchido, o site abre num modo demonstração: o formulário de fotos vira data URL e a página /solicitar mostra um banner avisando que a planilha/e-mail ainda não foram configurados.


2) Variáveis de ambiente

Copie .env.example para .env e preencha:

Variável Obrigatória? Descrição
GOOGLE_SERVICE_ACCOUNT_JSON ✅ (planilha) JSON completo do service account (com aspas simples no .env)
GOOGLE_SHEET_ID ✅ (planilha) ID da planilha (trecho entre /d/ e /edit da URL)
RESEND_API_KEY ✅ (e-mail) API key do Resend (https://resend.com)
RESEND_FROM ✅ (e-mail) Remetente verificado, ex: Araújo <site@seudominio.com>
NOTIFY_EMAIL ✅ (e-mail) E-mail que recebe a notificação (o do Araújo)
VITE_SUPABASE_URL ✅ (fotos) URL do projeto Supabase (é pública)
VITE_SUPABASE_ANON_KEY ✅ (fotos) Anon key do Supabase (é pública, mas revogável)
VITE_SUPABASE_BUCKET ✅ (fotos) Nome do bucket, ex: fotos-solicitacoes
API_PORT não Porta do backend local (padrão 8787)
SITE_URL não URL canônica das meta tags

⚠️ Nunca commite .env com credenciais reais (ele está no .gitignore). As variáveis VITE_* ficam públicas no bundle — use apenas chaves anon do Supabase; a política do bucket é o que protege (seção 5).


3) Google Sheets — integração real

  1. Crie o service account

  2. Ative a API — em APIs & Serviços → Biblioteca, ative a Google Sheets API no mesmo projeto.

  3. Crie/use a planilha

    • Crie uma planilha no Google Sheets e compartilhe com o e-mail do service account (o campo client_email do JSON) com papel Editor.
    • Copie o GOOGLE_SHEET_ID da URL: https://docs.google.com/spreadsheets/d/AQUI_FICA_O_ID/edit
  4. Aba "Solicitações" — renomeie a primeira aba pra Solicitações. O cabeçalho esperado (ordem fixa) está em server/lib/sheets.jsSHEET_HEADER. Se preferir criar na mão:

    Protocolo, Enviado em, Modalidade, Tipo, Plano, Status, Nome, Idade, E-mail,
    WhatsApp, Objetivo, Experiência, Lesões / limitações, Restrições médicas,
    Altura (cm), Peso (kg), Pescoço (cm), Ombro (cm), Peitoral (cm), Cintura (cm),
    Quadril (cm), Braço (cm), Antebraço (cm), Coxa (cm), Panturrilha (cm),
    Foto frente, Foto lado, Foto costas, Usar como depoimento, Consentimento LGPD
    
  5. Acompanhamento de status — a coluna Status nasce com pendente. Quando entregar a planilha personalizada, o Araújo troca pra planilha enviada na célula (ou numa automação/Apps Script, se preferir). O endpoint GET /api/status?id=AR-... devolve o status atual — útil pra um painel simples. Uma aba "Status" extra pode ser adicionada na planilha (coluna Protocolo + Status) alimentada manualmente ou por Apps Script; o site não depende dela.


4) E-mail de notificação (Resend)

  1. Crie conta em https://resend.com e gere uma API key.
  2. Verifique um domínio (ou use o domínio onboarding@resend.dev apenas pra testar) e use o e-mail verificado em RESEND_FROM.
  3. NOTIFY_EMAIL = e-mail do Araújo.

A cada envio, o Araújo recebe um e-mail estruturado com os dados da triagem, as URLs das fotos e o protocolo. Alternativa SMTP: troque a função sendNotification em server/lib/email.js por Nodemailer — a assinatura é a mesma.


5) Supabase Storage (fotos)

  1. Crie um projeto em https://supabase.com (plano free resolve).
  2. Em Storage, crie o bucket fotos-solicitacoes.
  3. Política de segurança (SQL editor):
-- Upload com a chave anônima (o site) dentro de solicitacoes/*
create policy "upload anon solicitacoes"
on storage.objects for insert to anon
with check (bucket_id = 'fotos-solicitacoes'
  and (storage.foldername(name))[1] = 'solicitacoes');

-- Leitura pública das fotos (URLs usadas na planilha/e-mail)
create policy "select public fotos"
on storage.objects for select to anon
using (bucket_id = 'fotos-solicitacoes');
  1. Copie SUPABASE_URL e ANON_KEY (Project Settings → API) e o nome do bucket para as variáveis VITE_*.

As fotos ficam em solicitacoes/<protocolo>/frente|lado|costas.jpg — são essas URLs que vão pra planilha e pro e-mail (nunca o binário).


6) Deploy (Vercel)

npm i -g vercel
vercel
  • A pasta api/ é detectada automaticamente como serverless functions.
  • vercel.json já contém o rewrite de SPA (/((?!api/).*)/index.html).
  • Adicione as variáveis de ambiente no painel (Project → Settings → Environment Variables) — as mesmas do .env.example.
  • Netlify: build npm run build, public dir dist, adapte as funções para exports.handler (o import de server/lib funciona igual).

7) Imagem Open Graph

public/og-image.png (1200×630 com o logo de chifres) é gerada por um script sem dependências:

npm run og:image

Após publicar, confira o domínio em index.html (meta og:url e twitter:*).


8) Personalização rápida

O quê Onde
Número do WhatsApp src/data/site.jswhatsappNumber
Instagram / e-mail / cidade src/data/site.js
Preços src/data/plans.jspreco e precoNota
Depoimentos / antes-depois src/data/resultados.js
Perguntas frequentes src/data/faqs.js
Fotos reais de resultados trocar o bloco placeholder em src/pages/Resultados.jsx
Endereço físico / mapa src/pages/Contato.jsx (seção do mapa)
Design tokens (cores, fontes) tailwind.config.js (única fonte de verdade)

9) LGPD — notas

O formulário só envia dados com o consentimento explícito (checkbox LGPD). As fotos são usadas exclusivamente para montar/acompanhar o plano; divulgação como depoimento exige nova autorização específica em separado. Reveja o texto com um advogado antes do lançamento público.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages