Skip to content

Rodaviva29/secret-santa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🎁 WhatsApp Secret Santa

Secret Santa, now with superpowers. ✨

Participants sign up, build their wishlist, and the organiser runs a draw that respects exclusions, sets a budget, avoids repeating past pairings, and delivers results via a reveal page, WhatsApp, email or push. Schedule it for later, reveal the pairings on a date β€” or keep them secret forever.

Rewritten from the ground up: from an Express prototype β†’ Next.js 16 Β· React 19 Β· Better Auth Β· Postgres/Drizzle. Dockerised, deploy-ready for Coolify. 🐳

f70372d1-e83c-4261-a849-4ac7585abdcd

Next.js React Better Auth Postgres Docker Tailwind WhatsApp


✨ Features

Feature What it does
πŸ” Accounts Email/password login (Better Auth). The first user (or ADMIN_EMAIL) becomes admin automatically.
πŸ“ Wishlists Each participant lists what they'd like to receive β€” their santa sees it all.
🚫 Exclusions Forbidden pairs (couples, siblings) never draw each other.
πŸ’° Budget Optional per-draw budget, shown on the reveal page.
πŸ•°οΈ History Past draws are used to avoid repeating last year's pairing β€” and each member sees their own match history on their dashboard.
🎲 Robust algorithm Backtracking derangement β€” respects constraints, or fails with a clear error.
πŸ” Self-draw toggle Optional per-draw switch to allow being matched to yourself (off by default).
⏰ Schedule a draw Pick a date/time β€” the draw runs and delivers itself automatically (in-process scheduler).
πŸ‘€ Reveal pairings Choose a date when the full giverβ†’receiver list goes public (admin history + everyone's dashboard), or never.
πŸ“¬ Pick your delivery Per draw: reveal page, WhatsApp + link, or WhatsApp direct.
βœ‰οΈ Email (optional) Resend integration β€” emails the match to participants with a known account email.
πŸ”” Push (optional) Installable PWA with Web Push notifications when a match is ready.
πŸ”— Account linking Manually-added participants can later be linked to a real user account.
🌐 Site metadata Admin "Technical" tab edits OpenGraph title, description, icon and link-preview banner at runtime.
🏳️ Phone with flags Country dial-code picker with SVG flags + free-typed codes; stored WhatsApp-style.

πŸ“¬ Delivery modes

πŸ”—
Reveal
Private reveal links, with a per-link view limit.
πŸ’¬
WA + Link
WhatsApp message containing the reveal link.
πŸŽ…
WA Direct
WhatsApp message with the match's name in the template.

🧱 Stack

Layer Choice
πŸ–ΌοΈ Framework Next.js 16 (App Router) Β· React 19
πŸ” Auth Better Auth (+ admin plugin)
πŸ—„οΈ Database Postgres via Drizzle ORM (pg)
🎨 UI Tailwind CSS v4 · shadcn/ui · react-day-picker · flag-icons
πŸ“² Messaging Meta WhatsApp Cloud API Β· Resend (email) Β· Web Push (PWA)
⏰ Scheduling In-process poller via instrumentation.ts
🐳 Deploy Docker · docker-compose · Coolify-ready

πŸš€ Getting started

🐳 Option A β€” Docker (recommended)

Brings up the app and Postgres together. Migrations run automatically on start.

# 1️⃣  Configure
cp .env.example .env
#   β€’ BETTER_AUTH_SECRET  β†’  openssl rand -base64 32
#   β€’ ADMIN_EMAIL         β†’  the email you'll sign up with (becomes admin)
#   β€’ POSTGRES_*          β†’  credentials for the bundled database
#   β€’ WA_*                β†’  (optional) only for WhatsApp delivery

# 2️⃣  Build + run
docker compose up -d --build   # πŸ‘‰  http://localhost:3000

πŸ’» Option B β€” Local dev

# 1️⃣  Install
npm install

# 2️⃣  Configure (set DATABASE_URL to a running Postgres)
cp .env.example .env

# 3️⃣  Apply migrations
npm run db:migrate

# 4️⃣  Run
npm run dev      # πŸ‘‰  http://localhost:3000

πŸ’‘ Need a quick Postgres for local dev? docker compose up -d db starts just the database.

πŸ’‘ Sign up with ADMIN_EMAIL to get the admin role, then open /admin to add participants, set exclusions, choose delivery, and run the draw.


☁️ Deploy on Coolify

This repo ships a Dockerfile + docker-compose.yml, so Coolify can deploy it as a Docker Compose resource out of the box.

  1. New Resource β†’ Docker Compose, point it at this repo.
  2. Set the environment variables (Coolify reads them into the compose file):
    • BETTER_AUTH_SECRET β€” a long random string
    • BETTER_AUTH_URL / NEXT_PUBLIC_APP_URL β€” your public URL (e.g. https://santa.example.com)
    • ADMIN_EMAIL β€” the account to auto-promote to admin
    • POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB
    • WA_* β€” optional, only for WhatsApp delivery
    • RESEND_* β€” optional, for email delivery
    • VAPID_* / NEXT_PUBLIC_VAPID_PUBLIC_KEY β€” optional, for push notifications
  3. Deploy. πŸŽ‰ The bundled Postgres persists in the pgdata volume and migrations run automatically on every container start.

ℹ️ NEXT_PUBLIC_APP_URL is baked into the client at build time β€” set it before the image is built so reveal links use the right domain.

ℹ️ Prefer Coolify's managed Postgres instead of the bundled one? Remove the db service from the compose file and set DATABASE_URL to the managed instance's connection string.


πŸ“² WhatsApp setup

For wa_link / wa_direct you need a Meta WhatsApp Business account and an approved template with two body parameters:

Param Content
{{1}} The giver's name
{{2}} The match's name (wa_direct) or the reveal URL (wa_link)

Set WA_API_TOKEN, WA_PHONE_NUMBER_ID, WA_TEMPLATE_NAME, WA_TEMPLATE_LANGUAGE in .env. Reveal-page delivery needs none of this. βœ…


βœ‰οΈ Email setup (optional)

Powered by Resend. When configured, draw results are also emailed to participants whose account email is known.

RESEND_API_KEY="re_..."
RESEND_FROM="Secret Santa <santa@your.domain>"   # verified sender

Leave unset to disable email entirely. The admin Integrations card shows whether it's enabled.


πŸ”” Push notifications setup (optional)

The app is an installable PWA with Web Push. Generate a VAPID key pair once:

npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY="..."
NEXT_PUBLIC_VAPID_PUBLIC_KEY="..."   # same value, inlined into the client
VAPID_PRIVATE_KEY="..."
VAPID_SUBJECT="mailto:you@example.com"

ℹ️ NEXT_PUBLIC_VAPID_PUBLIC_KEY is baked in at build time (it's a Dockerfile build arg). Participants enable notifications from their dashboard.


πŸ› οΈ Scripts

Script What it does
npm run dev πŸ”₯ Development server
npm run build πŸ“¦ Production build
npm test πŸ§ͺ Draw-algorithm unit tests
npm run db:generate 🧬 Generate a Drizzle migration
npm run db:migrate ⬆️ Apply migrations
npm run db:studio πŸ” Open Drizzle Studio

πŸ—‚οΈ Structure

app/                  🧭  routes (auth, dashboard, admin, reveal, api, manifest)
components/           🧩  UI (shadcn + components)
lib/                  βš™οΈ  auth Β· db/schema Β· draw Β· draw-runner Β· scheduler
                          whatsapp Β· email Β· push Β· pairings Β· settings Β· phone
instrumentation.ts   ⏰  boots the in-process draw scheduler
public/              πŸ–ΌοΈ  PWA service worker + app icon
drizzle/             πŸ—ƒοΈ  SQL migrations
scripts/             πŸ“œ  database migration runner
Dockerfile           🐳  standalone production image
docker-compose.yml   🐳  app + Postgres (Coolify-ready)

πŸ“œ Versions

Branch What it is
🟒 v2 This rewrite (Next.js Β· Better Auth Β· Drizzle) β€” current branch
🟑 v1 The original Express prototype (static HTML + JSON)

🀝 Contributing

Pull requests welcome! If you'd like to enrich the project, open an issue or a PR. Any Ko-Fis given would be greatly welcome to allow me to continue to mantain this project development. If you have any questions or issues, feel free to contact me on Discord (prefereble) or via chat in https://chung-jf.me. My Discord nickname is Rodaviva. πŸŽ„

πŸ“„ License

MIT β€” see LICENSE.

πŸŽ„ Happy Xmas! 🎁

About

The Cool Integration for Xmas, Secret Santa with WhatsApp or a Reveal link!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Contributors