Landing page super minimalista para Allons. Negro, logo + un solo CTA → captura email → guarda en Supabase con atribución por QR.
- Next.js 15 (App Router)
- React 19
- Tailwind 4
- Supabase (tabla
waitlist)
cd allons-waitlist
pnpm install
cp .env.example .env.local # llena las 3 variables
pnpm dev.env.local:
NEXT_PUBLIC_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
El
SUPABASE_SERVICE_ROLE_KEYsolo se usa server-side en/api/waitlist. Nunca lo expongas con prefijoNEXT_PUBLIC_.
Opcional para enlaces compartidos y App Links:
APP_STORE_LINK=https://apps.apple.com/us/app/allons-eventos-honduras/id6780532182?uo=4
PLAY_STORE_LINK=https://play.google.com/store/apps/details?id=com.fndrs.allons
ANDROID_PACKAGE_NAME=com.fndrs.allons
ANDROID_SHA256_CERT_FINGERPRINTS=AA:BB:CC:DD:...
ANDROID_SHA256_CERT_FINGERPRINTS debe salir de Google Play App Signing. Sin ese valor, /.well-known/assetlinks.json responde [] y Android no verificará los App Links.
Abre tu proyecto → SQL Editor → pega y corre db/schema.sql.
Crea:
public.waitlistcon columnasemail,source,referer,user_agent,ip,created_at- Índice único en
lower(email)(un email solo se registra una vez) - View
waitlist_by_sourcepara ver el conteo por QR/ubicación - RLS encendido — solo el
service_role(el server) puede leer/escribir
Vercel:
vercel link
vercel env add NEXT_PUBLIC_SUPABASE_URL
vercel env add NEXT_PUBLIC_SUPABASE_ANON_KEY
vercel env add SUPABASE_SERVICE_ROLE_KEY
vercel env add APP_STORE_LINK
vercel env add PLAY_STORE_LINK
vercel env add ANDROID_SHA256_CERT_FINGERPRINTS
vercel --prod/events/{id}muestra una página de respaldo para quien abre un evento compartido sin tener la app.- El botón principal intenta abrir
allons://events/{id}. /.well-known/apple-app-site-associationhabilita/verify,/ticketsy/eventspara iOS./.well-known/assetlinks.jsonse genera desdeANDROID_SHA256_CERT_FINGERPRINTSpara Android.
La landing lee el query param ?src=. El valor se guarda en la columna source.
URL → https://allonsapp.com/?src=la20
Insert → { email: "...", source: "la20" }
La generación de QRs se gestiona desde allons-admin, no desde este repo.
Usa la vista /waitlist-qr del panel admin o el script pnpm run qr en
allons-admin.
- Solo
a-z,0-9,-,_. Máx. 40 chars. - El backend valida con regex; cualquier slug "raro" se guarda como
null(= directo). - Mantén el slug igual entre reprints de la misma ubicación.
En SQL Editor de Supabase:
-- Resumen agregado
select * from waitlist_by_source;
-- Detalle de la última semana, por ubicación
select source, email, created_at
from waitlist
where created_at > now() - interval '7 days'
order by created_at desc;
-- Conversión por día y por QR
select
date_trunc('day', created_at) as day,
coalesce(source, '(direct)') as source,
count(*) as signups
from waitlist
group by 1, 2
order by 1 desc, 3 desc;.
├── db/schema.sql # corre esto en Supabase
├── public/ # logo Allons
└── src/
├── app/
│ ├── api/waitlist/route.ts # POST endpoint (server-side, service_role)
│ ├── page.tsx # landing
│ ├── layout.tsx
│ └── globals.css
├── components/
│ ├── AllonsLogo.tsx
│ └── WaitlistForm.tsx # CTA → email → submit
└── lib/
└── supabase-server.ts # admin client