Mike Johnston b3f3bd394e
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 30s
fix stale auth permisisons
2026-03-20 22:17:50 -04:00
2026-02-28 00:01:41 -05:00
2026-03-20 11:08:02 -04:00
2026-03-20 22:17:50 -04:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:01:41 -05:00
2026-02-28 00:24:08 -05:00
2026-02-28 01:50:20 -05:00

Loot Hunt

A digital alternate reality game — find and scan hidden QR codes in real life to earn points and climb the leaderboard.

How It Works

  1. Admins create hunts, manage all content, assign roles, and reset passwords
  2. Organizers create and manage their own hunts with printable QR code cards
  3. Players scan hidden QR codes to earn points — first find gets the most points
  4. Leaderboards track top players per hunt and globally

Point System

Scan Order Points
1st scan 500
2nd scan 250
3rd scan 100
4th+ 50

Players earn points only once per package. Re-scanning lets you update the package hint.

Roles

Capability Admin Organizer Player
Create hunts Yes Yes No
Manage/edit/delete own hunts Yes Yes No
Manage other users' hunts Yes No No
Download QR code PDFs Yes Own hunts No
Password reset Yes No No
Delete any image / clear hints Yes No No
Assign organizer role Yes No No

Features

  • QR Code Cards — Printable Avery 5371 format PDFs with double-sided backs
  • First Finder Photos — First scanner can upload/replace an image per package
  • Hints — Most recent scanner can leave a message for the next finder
  • Player Profiles — Stats, rank, hunt breakdown, and recent activity
  • Dark Mode — Toggle with system preference detection and localStorage persistence
  • Relative Timestamps — "3h ago" format with full date on hover
  • Flash Messages — Feedback on actions (create, edit, delete, upload, etc.)
  • Paginated Leaderboards — 25 per page with navigation controls
  • Admin Dashboard — Hunt stats, top finders, discovery rate, recent scans, role management

Tech Stack

  • Node.js + Express
  • SQLite via sql.js (WASM)
  • EJS templates
  • PDFKit + qrcode for printable QR sheets
  • Docker deployment via Portainer

Quick Start (Development)

cp .env.example .env
npm install
node src/setup-admin.js admin yourpassword
npm run dev

Visit http://localhost:3000

Docker Deployment

The project deploys via Gitea Actions → Docker build → Portainer stack update.

# Build locally
docker build -t loot-hunt .

# Run
docker run -p 3000:3000 -v loot-data:/app/data \
  -e SESSION_SECRET=your-secret \
  -e BASE_URL=https://loot-hunt.com \
  loot-hunt

# Create admin user inside container
docker exec -it loot-hunt node src/setup-admin.js admin yourpassword

Environment Variables

Variable Description Default
PORT Server port 3000
NODE_ENV Environment production
BASE_URL Public URL (for QR codes) http://localhost:3000
SESSION_SECRET Session encryption key (required)
DB_PATH SQLite database path ./data/loot-hunt.db
UPLOADS_DIR Image uploads directory ./data/uploads
TRUST_PROXY Trust reverse proxy headers false

Project Structure

src/
├── app.js              # Express application entry point
├── setup-admin.js      # CLI tool to create/promote admin users
├── config/
│   └── database.js     # SQLite (sql.js) initialization, schema & migrations
├── middleware/
│   └── auth.js         # Auth, admin & organizer middleware
├── models/
│   └── index.js        # All database operations
├── routes/
│   ├── auth.js         # Login/register/logout/password reset
│   ├── admin.js        # Hunt management, PDF download, roles, password reset
│   ├── loot.js         # QR scan handling, image upload, hints
│   └── hunts.js        # Public hunt profiles, leaderboards, player profiles
├── utils/
│   └── pdf.js          # Avery 5371 QR code PDF generation
└── views/              # EJS templates
public/
├── css/
│   └── style.css       # Styles with dark mode support
└── js/
    └── timeago.js      # Relative timestamp formatting
Description
No description provided
Readme 480 KiB
Languages
EJS 46.3%
JavaScript 43.2%
CSS 10.4%
Dockerfile 0.1%