Skip to content

badbread/simplyraffle

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

179 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simply Raffle

Web-based raffle management system for schools, nonprofits, and community organizations.

Setup

1. Generate credentials

You need three things before starting:

Admin password hash (SHA-256 — no $ signs, safe for Docker Compose and Portainer):

# Linux/Mac:
echo -n "yourpassword" | sha256sum | cut -d' ' -f1

# Windows (PowerShell):
python -c "import hashlib; print(hashlib.sha256(b'yourpassword').hexdigest())"

# Node.js:
node -e "const c=require('crypto'); console.log(c.createHash('sha256').update('yourpassword').digest('hex'))"

Session secret (must be 32+ characters):

openssl rand -hex 32

Strong database password: pick anything secure.

2. Create your .env file

Copy .env.example to .env and fill in the values:

cp .env.example .env
Variable Description
POSTGRES_USER DB username (e.g. raffle)
POSTGRES_PASSWORD Strong DB password
POSTGRES_DB DB name (e.g. raffle)
APP_PORT Port on the NAS (e.g. 3456)
ADMIN_USERNAME Login username for admin panel
ADMIN_PASSWORD_HASH bcryptjs hash of your admin password
SESSION_SECRET 32+ char random string
NEXT_PUBLIC_BASE_URL Full URL students use (e.g. http://nas3:3456)

3. Build and start (direct Docker Compose)

docker-compose up -d --build

Access the admin panel at: http://nas3:3456/admin/dashboard


Portainer Deployment (NAS3)

Since Portainer cannot read .env files from NFS, you must provide environment variables via the Portainer UI when creating the stack.

Portainer: http://10.1.10.21:9000 · Endpoint: 14 (dockerLXC)

Steps:

  1. Build the image (first time or after code changes):

    # SSH into NAS3 or run from the NAS console
    cd /volume1/docker/zz_claude/raffle
    docker build -t raffle-app:latest .
  2. In Portainer → Stacks → Add Stack:

    • Name: raffle
    • Web editor: paste docker-compose.yml content
    • Important: Portainer caches compose files. Always DELETE the stack and CREATE a new one for updates.
  3. Set environment variables in Portainer's "Environment variables" section:

    POSTGRES_USER=raffle
    POSTGRES_PASSWORD=your-strong-password
    POSTGRES_DB=raffle
    APP_PORT=3456
    ADMIN_USERNAME=admin
    ADMIN_PASSWORD_HASH=240be518fabd2724ddb6f04eeb1da5967448d7e831c08c8fa822809f74c720a9
    SESSION_SECRET=your-32-char-secret
    NEXT_PUBLIC_BASE_URL=http://nas3:3456
    

    (The hash above is SHA-256 of admin123 — generate your own with echo -n "yourpassword" | sha256sum)

  4. Deploy — the app will automatically run database migrations on startup.


How it works

Admin workflow

  1. Go to /admin/dashboard, sign in
  2. Prizes: Add prizes with a ticket cost (e.g. "Gaming Chair = 5 tickets/entry")
  3. Students: Add students individually or import a CSV, assign ticket balances
  4. Share magic links with students (copy from the Students table, or export a CSV with all links)
  5. Open the raffle on the Dashboard
  6. Monitor entries in the Entries tab
  7. When ready: Close the raffle, then go to Draw and run the draw
  8. Winners are displayed and can be exported as CSV

Student workflow

  1. Student receives their unique magic link (e.g. http://nas3:3456/enter?token=...)
  2. Opens the link — no login/password needed
  3. Allocates tickets to prizes using the +/− buttons
  4. System enforces they can't use more tickets than their balance
  5. Can re-allocate freely while the raffle is open

CSV import format

name,email,tickets
Alice Smith,alice@school.edu,10
Bob Jones,bob@school.edu,8
Carol White,,12

After import, a CSV of magic links is available for download.

Ticket mechanics

  • Each prize has a ticket cost — the number of tickets per entry slot
  • Students allocate tickets in multiples of that cost
  • E.g. if Gaming Chair costs 5 tickets: 5 tickets = 1 entry, 10 tickets = 2 entries (better odds)
  • The weighted random draw gives proportionally higher odds for more entries

Future: Moving to public hosting

When the raffle moves to the school's public website:

  1. Replace raffle-db container with a managed PostgreSQL service:

    • Railway — easiest, free tier available
    • Neon — serverless Postgres, generous free tier
    • Supabase — free tier, includes dashboard
  2. Update DATABASE_URL to the managed Postgres connection string

  3. Update NEXT_PUBLIC_BASE_URL to the public domain

  4. The raffle-app container can be deployed to:

    • Railway (auto-deploys from the Dockerfile)
    • Render, Fly.io, or any Docker-compatible host

No code changes required — only environment variable updates.

About

Production SaaS — Cloudflare Workers, Next.js 14, Stripe, Docker. Magic-link auth, edge payment validation, weighted random draw. Shipped solo.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors