Code && Chill is a Go web application for running puzzle events with:
- Time-based puzzle unlocks
- Per-user progress tracking
- Discord OAuth login
- Admin user management
- Optional Discord notifications
It stores data in BoltDB and serves a website from files in data/.
- Multi-event puzzle support via YAML config
- Puzzle pages with part-by-part answer submission
- Unlock scheduling and latest-puzzle redirect
- Session management with expiration and cleanup
- Admin pages for users and puzzles
- JSON admin API for user listing and updates
- Optional HTTPS with live TLS certificate reload
- Automatic database backups on cron
- Go 1.26+
- A Discord application (for OAuth)
- A Discord bot token (optional, for notifier integration)
cmd/code-and-chill: main web servercmd/api: API client CLI for user admin operationscmd/listdb: inspect BoltDB contentscmd/fakeusers: seed fake users/progress for testingconfig.yaml: runtime configurationdata/: static files, templates, and HTML pagesdb/: BoltDB storage location (default:db/cc.db)bak/: database backup output directorysecret/: secret files referenced byconfig.yaml
- Create secret files referenced by
config.yaml:
secret/discord.clientsecret.txt
secret/discord.token.txt
- Update
config.yamlvalues for your environment:
server.port,server.host,server.dataDirauth.discord.clientID,auth.discord.redirectURI,auth.discord.guildIDnotifier.baseURIandnotifier.discord.channelspuzzles.events[*].configpaths
- Run the app:
go run ./cmd/code-and-chillTo use a custom config file:
go run ./cmd/code-and-chill path/to/config.yamlBuild all commands into bin/:
./build.shRun tests:
./test.shEquivalent direct commands:
GOBIN=$PWD/bin go install ./...
go test -timeout 30s ./... -vThe app uses strict YAML decoding, so unknown fields in config.yaml will fail startup.
Top-level sections:
serverdbsessionauthnotifierpuzzles
Key settings:
server.port: main web server portserver.apiPort: localhost-only admin API port (0disables separate API server)server.tlsCertFile+server.tlsKeyFile: enable HTTPSserver.tlsReloadSchedule: cron schedule to reload TLS cert/keyserver.httpsRedirect: optional HTTP :80 -> HTTPS redirectdb.backupSchedule: cron schedule for DB backupssession.expire,session.truncate,session.cleanupSchedule: session lifecycleauth.discord.clientSecret: path to file containing Discord client secretnotifier.discord.token: path to file containing Discord bot tokenpuzzles.default: default event pathpuzzles.events[*].config: event configuration file path
Puzzle definitions are loaded from the files referenced in puzzles.events[*].config.
Event config includes:
- event
id,name - list of puzzles with unlock times and puzzle config file paths
Puzzle config includes:
- puzzle
id,path,name parts: markdown files for each partinputs: input files plus expected answers per part
Two access patterns exist:
- Main server routing under
/api/*(admin web context, requires admin account) - Separate localhost API server on
server.apiPort(direct endpoints)
Direct endpoints (no /api prefix):
GET /usersGET /users?name=<query>GET /user/{id}POST /user/{id}
Example update payload:
{
"admin": true
}Run the helper CLI against the API port (default shown in config.yaml: 1274):
go run ./cmd/api --port 1274 user list
go run ./cmd/api --port 1274 user find "alice"
go run ./cmd/api --port 1274 user get <user-id>
go run ./cmd/api --port 1274 user update <user-id> --admin
go run ./cmd/api --port 1274 user update <user-id> --unset-adminInspect DB content:
go run ./cmd/listdb
go run ./cmd/listdb path/to/db-fileSeed fake users/progress (development/testing):
go run ./cmd/fakeusers
go run ./cmd/fakeusers path/to/db-file- The server expects website content and templates under
server.dataDir(default:data). - If
server.hostis set, host validation middleware is enabled. - DB backups are triggered by cron and also once on process shutdown.