Skip to content

notfixingit3/waffle

Repository files navigation

Project Syrup logo

Project Syrup - The Waffle Maker

A dead-simple spot board for Instagram waffle drops. Built for collectors, by collectors.

Docker Go PostgreSQL GHCR WebSockets

Live Demo: [Coming Soon] | Latest Release: v0.1.11


What is this?

Project Syrup is a mobile-first live spot management system for Instagram waffle sellers. No timers. No randomizers. No payment processing. Just a clean, real-time board where buyers claim spots and admins track payments.

Built to work inside Instagram's in-app browser because that's where your buyers already are.

The Flow

  1. Admin creates a waffle — sets title, price per spot, total spots, links to Instagram posts showing what's being waffled
  2. Buyers claim spots — tap available spots, enter Instagram handle, done (< 10 seconds)
  3. Admin marks paid — as payments come in via DM/CashApp/Venmo
  4. Winner drawn — admin enters winning spot number after external drawing
  5. Everyone sees results — instant WebSocket broadcast to all connected clients

Screenshots

Screenshot Screenshot
Public Home
Public home page showing active waffles
Admin Login
Admin login page
Admin Dashboard
Admin dashboard with waffle cards
Waffle Management
Waffle management spot grid with mixed spot statuses
Admin Management
Admin management table
Reports
Admin reports page
About Page
Public about page with admin extras

Features

  • Multi-admin auth — Role-based access control with super_admin, admin, and waffle_manager roles
  • Admin management — Create admins, change roles, deactivate accounts, and reset another admin's password (super_admin only)
  • waffle_manager role — Create and manage waffles + view reports, without archive/delete/user-management access
  • Timezone settings — Per-admin timezone preference with IANA timezone dropdown in settings page
  • Password reset — Self-service reset tokens plus authenticated password changes
  • Instagram media links — Link to posts showing what's being waffled (supports multiple items)
  • Archive + delete controls — Hide completed waffles by default, or type DELETE for permanent removal
  • Real-time spot grid — WebSocket-powered claim, payment, release, and winner updates
  • Mobile-first public flow — Built for fast spot claims inside Instagram's in-app browser
  • Installable app shell — Web App Manifest, app icons, and standalone display metadata are wired in
  • Admin dashboard — Create waffles, manage spots, track payments, enter winners
  • Admin reports — Drought list, power buyers, monthly activity, and spot velocity reports
  • Buyer stats — Track win/loss history per Instagram handle
  • Activity history — Record claim, payment, release, and winner events per waffle
  • CSV exports — Download a waffle's spot list for external reconciliation
  • Transactional safety — No double-claims, ever
  • Light/dark mode — Manual theme toggle with persisted preference
  • Dual clock footer — Server UTC time + local browser time with waffle counter
  • Winner management — Admin-only clear/change winner with buyer stats recalculation
  • Login history — Audit trail with async WHOIS IP enrichment (org, country, city, ASN)
  • Settings dropdown — Consolidated admin menu under username (Settings, History, About, Theme, Logout)
  • About page — Public about page with admin-only system extras
  • Configurable WHOIS — Super_admin can configure WHOIS server for IP lookups
  • Admin audit log — Admin and super_admin users can review audited state changes with filters and pagination
  • Security hardening — Structured logging, health/readiness probes, secure cookies, login lockout, password policy, and destructive action password confirmation

Quick Start

Prerequisites: Docker and Docker Compose.

# Clone the repo
git clone https://github.com/notfixingit3/waffle.git
cd waffle

# Start everything
docker compose up --build

Docker Compose starts both the Go app and PostgreSQL, runs database migrations, and injects safe local-development defaults for the database connection, JWT secret, and admin credentials. You do not need to create a .env file to run the app locally.

After startup, open the app and admin tools here:

Service URL
Application http://localhost:8383
Admin Login http://localhost:8383/admin/login
PostgreSQL localhost:5432

Default local admin credentials are admin / syrup. Change them before any real deployment.


Production Deployment

Prerequisites: Docker and Docker Compose v2+.

  1. Copy docker-compose.prod.yml to your server
  2. Create a .env file (see .env.example for reference):
    WAFFLE_VERSION=v0.1.16
    DATABASE_URL=postgres://user:password@postgres:5432/syrup?sslmode=disable
    JWT_SECRET=your-secure-random-secret-here
    ADMIN_PASSWORD=your-secure-admin-password
  3. Start the services:
    docker compose -f docker-compose.prod.yml up -d
  4. Open /admin/login and change the default admin password immediately

Pre-built images are available at ghcr.io/notfixingit3/waffle for linux/amd64 and linux/arm64.

Release Channels

The following channels are available for the Docker image:

Channel Tag Description
Stable latest Tracks the latest stable release from the main branch. Recommended for production.
Dev dev Tracks the latest build from the dev branch. For testing and staging only. May be unstable.
Pinned v0.1.16 A specific stable version. Recommended for reproducible deployments.

The stable channel is currently in production testing. Pin to specific versions for critical deployments.


Tech Stack

Layer Technology
Frontend Go server-side templates + Tailwind CSS + DaisyUI
Backend Go (Gin), WebSocket hub
Database PostgreSQL with migrations
DevOps Docker Compose, multi-stage builds
PWA Web App Manifest, app icons, standalone display metadata

Project Status

Phase Status Description
1 ✅ Complete Docker Compose + Postgres + Go health check + server-rendered UI
2 ✅ Complete Waffle schema + create endpoint + public page + spot grid + Instagram media links
3 ✅ Complete Spot claims + pending status + admin dashboard + mark paid/release + archive + delete
4 ✅ Complete WebSocket live updates + activity feed + buyer stats + admin reporting
5 ✅ Complete Manual winner entry + winner/loser marking + buyer stats + history
6 ✅ Complete Mobile polish + production Dockerfiles + deployment docs
7 ✅ Complete Multi-admin auth + role-based access + password reset + admin management + archive/delete
8 ✅ Complete Offline/service worker support with installable app shell, offline page caching, and update notifications
9 ✅ Complete DaisyUI migration (Halloween/syrup theme + amber primary)
10 ✅ Complete Production hardening (structured logging, health probes, graceful shutdown, rate limiting, Docker hardening)
11 ✅ Complete Admin audit/security polish (audit log, password policy, lockout, destructive confirmations)
12 ✅ Complete Bugfix/polish release (archived filters, buyer stats recalculation, password reset response, accessibility polish)

Architecture

┌──────────────────┐     ┌─────────────┐
│  Go (Gin)        │────▶│ PostgreSQL  │
│  Server Templates │◄────│   (pgx)     │
│  + WebSocket Hub │     └─────────────┘
└──────────────────┘
        │
        ▼
  Tailwind CSS
  (server-rendered)

Design principles:

  • Keep it simple and boring
  • No microservices
  • WebSocket server stays inside Go backend
  • Avoid premature abstractions
  • Readable names over clever ones

API Overview

Public Endpoints

  • GET /api/waffles — List public waffles
  • GET /api/waffles/:slug — Get waffle details
  • GET /api/waffles/:slug/spots — Get spot grid
  • GET /api/waffles/:slug/export — Export spots as CSV
  • POST /api/claims — Claim spots
  • GET /api/buyers/:handle/stats — Buyer win/loss stats
  • GET /api/buyers/:handle/history — Buyer claim history

Public Pages

  • GET / — Home page
  • GET /waffles — Waffle list
  • GET /waffle/:slug — Waffle detail + live spot grid
  • GET /buyer/:handle — Buyer stats page

Admin Auth Endpoints

  • POST /api/admin/login — Username/password login
  • POST /api/admin/forgot-password — Request password reset
  • POST /api/admin/reset-password — Reset password with token

Admin Endpoints (auth required)

  • GET /api/admin/me — Get current admin info
  • PATCH /api/admin/me/timezone — Update timezone preference
  • POST /api/admin/change-password — Change password
  • GET /api/admin/waffles?archived=true|false — List waffles
  • POST /api/admin/waffles — Create waffle
  • PATCH /api/admin/waffles/:id — Update waffle
  • POST /api/admin/waffles/:id/archive — Archive waffle
  • POST /api/admin/waffles/:id/unarchive — Unarchive waffle
  • DELETE /api/admin/waffles/:id — Permanently delete waffle
  • POST /api/admin/spots/:id/pay — Mark spot paid
  • POST /api/admin/spots/:id/release — Release pending spot
  • POST /api/admin/waffles/:id/winner — Enter winner
  • GET /api/admin/admins — List all admins (super_admin only)
  • POST /api/admin/admins — Create new admin (super_admin only)
  • PATCH /api/admin/admins/:id — Update admin role (super_admin only)
  • PATCH /api/admin/admins/:id/password — Reset another admin's password (super_admin only)
  • DELETE /api/admin/admins/:id — Deactivate admin (super_admin only)
  • GET /api/admin/reports/drought — Drought list report
  • GET /api/admin/reports/power-buyers — Power buyers report
  • GET /api/admin/reports/monthly-activity — Monthly activity report
  • GET /api/admin/reports/spot-velocity — Spot velocity report

Contributing

This is a personal project, but issues and PRs are welcome. The codebase prioritizes:

  1. Correctness — Server-side validation for every state change
  2. Performance — Sub-10-second claim flow on mobile
  3. Simplicity — No over-engineering, clear service boundaries

Special Thanks

Project Syrup exists because two glass artists kept running great waffles the hard way.

Dani Boo Glass
Dani Boo Glass on Instagram
Crysis Designs
Crysis Designs on Instagram

Special shout out to Dani Boo Glass and Crysis Designs for creating the original Waffle and for driving me nuts watching them copy/paste spot lists over and over again in chat.


Support

If this project helps you run smoother waffles, consider buying me a coffee:

Buy Me A Coffee


License

MIT — do whatever you want, just don't blame me when your waffle fills up in 30 seconds.


Built with 🧇 and questionable sleep habits.

About

A dead-simple live spot board for Instagram waffle drops. Built for collectors, by collectors.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors