Nigeria's most transparent digital raffle platform. Win real assets at affordable ticket prices.
- Frontend: Next.js 16 (App Router) + TypeScript + Tailwind CSS v4
- Backend: Supabase (Auth + Postgres + RLS)
- Payments: Paystack
- Hosting: Vercel
npm install --include=devNote:
--include=devis required to install Tailwind CSS (a devDependency).
- Create a project at supabase.com
- Run the full schema in Supabase > SQL Editor:
supabase/migrations/001_initial_schema.sql - Copy your project URL and API keys from Settings > API
- Get your keys from paystack.com Dashboard
- Register webhook URL:
https://yourdomain.com/api/webhooks/paystack - Enable
charge.successevent
Copy .env.example to .env.local and fill in all values:
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ...
NEXT_PUBLIC_PAYSTACK_PUBLIC_KEY=pk_live_...
PAYSTACK_SECRET_KEY=sk_live_...
NEXT_PUBLIC_APP_URL=https://yourdomain.comnpm run devAfter signing up, promote yourself to admin in Supabase SQL editor:
UPDATE public.profiles
SET role = 'admin'
WHERE email = 'your-email@example.com';| URL | Description |
|---|---|
/ |
Homepage |
/raffles |
Browse active raffles |
/raffles/[slug] |
Raffle detail + buy tickets |
/winners |
Public draw transparency page |
/how-it-works |
Platform explainer |
/dashboard |
User dashboard (tickets, wins) |
/vendor/apply |
Vendor application |
/vendor/dashboard |
Vendor portal |
/admin/dashboard |
Admin panel |
/admin/vendors |
Approve vendors |
/admin/raffles/[id] |
Approve + trigger draws |
User → Buy Ticket → POST /api/payments/initialize
→ Paystack authorization_url
→ User pays on Paystack
→ Paystack webhook → POST /api/webhooks/paystack
→ Ticket status = PAID
→ tickets_sold increments via DB trigger
Only the webhook confirms tickets. The redirect URL is for UX only.
- Admin clicks "Trigger Draw" on raffle page
- All paid ticket IDs collected and sorted
- 32-byte random seed generated via
crypto.randomBytes draw_hash = SHA-256(seed + ticket_ids.join(','))winner_index = BigInt('0x' + SHA-256(seed)) % BigInt(totalTickets)- Seed and hash published publicly on
/winners
Anyone can independently verify the result.
Create two public buckets:
raffle-images(5MB limit)avatars(2MB limit)
npx vercel --prodAdd all environment variables in Vercel Dashboard > Project > Settings > Environment Variables.