This app facilitates the Digital Draw process at Harvey Mudd, encoding all of the rules for Room Draw for pulling rooms.
If you just want to get running quickly using the shared staging database:
# 1. Setup frontend env
cp frontend/.env.example frontend/.env
cd frontend && npm install
# 2. Setup backend env (get credentials from Tom Lam - tomqlam [at] gmail [dot] com)
cp backend/.env.example backend/.env
# Then edit backend/.env and fill in the values
# 3. Start backend (in one terminal)
cd backend
docker build -t roomdraw-backend .
docker run -it -p 8080:8080 -v $(pwd):/app roomdraw-backend
# 4. Start frontend (in another terminal)
cd frontend && npm start
# 5. Open http://localhost:3000Note: Ask Tom Lam (tomqlam [at] gmail [dot] com) for staging database and BunnyNet credentials. For local development with your own database, see the full setup below.
- Docker - For running the backend server
- Node.js (v18+) - For the React frontend
- Python 3.12+ - For database setup scripts
- PostgreSQL 16+ - For local development database
- Docker Desktop Documentation - Main documentation
- Install on Windows
- Install on Mac
- Install on Linux
- Official Downloads - Download installers
- Installing via Package Manager - Recommended for most users
- npm Documentation - Includes nvm (version manager) instructions
- Official Downloads - Download installers
- Beginner's Guide - Platform-specific instructions
- Real Python Installation Guide - Detailed walkthrough
- Official Downloads - All platforms
- Postgres.app - Easiest option for Mac
- Installation Tutorial - Official documentation
Homebrew simplifies installing most dependencies on Mac:
# Install Homebrew first
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Then install dependencies
brew install node python postgresql@16
brew install --cask dockerSee Homebrew Installation Docs for details.
- Set up the database (see Database Setup below)
- Configure environment files (see Environment Configuration below)
- Start the backend:
cd backend && docker build -t roomdraw-backend . && docker run -it -p 8000:8000 -v $(pwd):/app roomdraw-backend - Start the frontend:
cd frontend && npm install && npm start - Open http://localhost:3000
The frontend needs frontend/.env to know where the backend API is running:
cp frontend/.env.example frontend/.envFor local development (default):
REACT_APP_API_URL=http://localhost:8080For production, this would point to your deployed backend URL.
The backend looks for backend/.env. Copy the template and fill in your values:
cp backend/.env.example backend/.envFor local development (create backend/.env):
# Database connection
SQL_PASS="your_local_postgres_password"
SQL_IP="host.docker.internal" # For Docker to connect to host machine's PostgreSQL
SQL_USER="postgres"
SQL_DB_NAME="roomdraw"
SQL_PORT="5432"
USE_SSL="disable" # Use "disable" for local, "require" for cloud/production
# Authentication
REQUIRE_AUTH="False" # Set to "False" to bypass Google OAuth during development
# BunnyNet CDN (required for suite design images)
BUNNYNET_WRITE_API_KEY="<get from Tom Lam>"
BUNNYNET_READ_API_KEY="<get from Tom Lam>"
BUNNYNET_STORAGE_ZONE="digidraw-production"
CDN_URL="https://digitaldraw.b-cdn.net"
# Email notifications (optional for local dev)
EMAIL_USERNAME=""
EMAIL_PASSWORD=""For staging/production (see backend/.env.production):
# Database - connects to HMC's server
SQL_PASS="<password>"
SQL_IP="ark.cs.hmc.edu"
SQL_USER="roomdraw24"
SQL_DB_NAME="roomdraw24"
SQL_PORT="5432"
USE_SSL="require"
# Authentication enabled
REQUIRE_AUTH="True"
# BunnyNet CDN
BUNNYNET_WRITE_API_KEY="<api-key>"
BUNNYNET_READ_API_KEY="<api-key>"
BUNNYNET_STORAGE_ZONE="digidraw-production"
CDN_URL="https://digitaldraw.b-cdn.net"
# Email notifications (HMC SMTP)
EMAIL_USERNAME="<hmc-username>"
EMAIL_PASSWORD="<password>"The database scripts look for database/.env. Copy the template and fill in your values:
cp database/.env.example database/.envVariables:
| Variable | Description |
|---|---|
SQL_PASS |
Database password |
SQL_IP |
Database host (localhost for local, IP for cloud) |
SQL_DB_NAME |
Database name |
SQL_USER |
Database username |
Note: The database scripts use
SQL_*variable names. Make sure your.envmatches this format.
-
Install PostgreSQL and create a database:
createdb roomdraw
-
Install Python dependencies:
cd database pip install -r requirements.txt -
Configure
database/.envwith your local PostgreSQL credentials -
Create all tables:
python createAllTables.py
-
Populate dorm data:
python createDorms.py
-
(Optional) Populate test user data using the Jupyter notebooks:
FakePopulate.ipynb- Creates fake test usersinsertNumbers.ipynb- Assigns draw numbersinsertPreplacements.ipynb- Sets up preplaced users
To run notebooks, install Jupyter:
pip install jupyterthenjupyter notebookSee Installing Jupyter for more details.
The setup scripts create the following tables in order:
- Suites - Dorm suites (groups of rooms)
- SuiteGroups - Groups of users pulling together
- Users - Student information and draw numbers
- Rooms - Individual rooms within suites
- user_rate_limits - Rate limiting and blocklist tracking
- transaction_logs - Audit log for room changes
BunnyNet is used for storing suite design images uploaded by students.
- Create a BunnyNet account at https://bunny.net
- Create a Storage Zone from the Storage tab in the dashboard
- Choose a main storage region closest to your users
- Optionally add replication regions (cannot be removed later)
- Get your API keys: Go to Storage Zone → FTP & API Access → copy the Password
- Create a Pull Zone connected to your Storage Zone:
- Go to CDN → Add Pull Zone → Select "Storage Zone" as origin type
- This gives you the CDN URL (e.g.,
https://your-zone.b-cdn.net)
- Add all values to your backend
.envfile
Resources:
For shared staging environments with a cloud-hosted PostgreSQL database:
- Enable the Cloud SQL Admin API in Google Cloud Console
- Go to Cloud SQL → Create Instance → Choose PostgreSQL
- Configure instance settings:
- Choose a region close to your users (cannot be changed later)
- Set a password for the
postgresuser
- Configure authorized networks to allow connections from developer IPs
- Create a database and user for the application
- Use the instance's public IP and credentials in your
.env
Resources:
Email notifications use Harvey Mudd's SMTP server. Contact the HMC CS department for SMTP credentials if you need to test email functionality.
Currently, we're just using my (tomqlam [at] gmail [dot] com) email for notifications, which is kinda scuffed. You can edit the .production.env file to use your own email username and password.
cd backend
# Development with live reload:
docker build -t roomdraw-backend .
docker run -it -p 8080:8080 -v $(pwd):/app roomdraw-backendThe backend runs on http://localhost:8080
cd frontend
npm install
npm startThe frontend runs on http://localhost:3000
For production, use Podman and the production environment file:
cd backend
podman build -t roomdraw-backend --build-arg ENV=production .
podman run -it -p 8000:8000 -v $(pwd):/app roomdraw-backendroomdraw/
├── backend/ # Go backend (Gin framework)
│ ├── cmd/server/ # Main entry point
│ ├── pkg/
│ │ ├── handlers/ # API route handlers
│ │ ├── middleware/# Auth, rate limiting, request queue
│ │ ├── models/ # Database models and types
│ │ ├── config/ # Environment configuration
│ │ └── database/ # Database connection
│ └── Dockerfile
├── frontend/ # React frontend
│ ├── src/
│ │ ├── App.js # Main component
│ │ ├── MyContext.js # Global state management
│ │ ├── components/
│ │ ├── Admin/ # Admin-only features
│ │ └── Search/ # Search functionality
│ └── package.json
└── database/ # Database setup scripts
├── *.sql # Table creation scripts
├── *.json # Dorm room data
├── *.py # Setup scripts
└── *.ipynb # Data population notebooks
- Use
host.docker.internalas the SQL_IP instead oflocalhost - Ensure PostgreSQL is configured to accept connections (check
pg_hba.conf)
- Set
REQUIRE_AUTH="False"in backend.envto bypass auth during development - For production, ensure Google OAuth is properly configured
- Verify PostgreSQL is running:
pg_isready - Check credentials in
.envmatch your database setup - For Cloud SQL, ensure your IP is in the authorized networks
This section covers deploying RoomDraw on Harvey Mudd's CS department servers.
For experienced deployers who understand the architecture:
# 1. SSH to Knuth and clone repo
ssh USERNAME@knuth.cs.hmc.edu
git clone https://github.com/tomqlam/roomdraw.git ~/workspaces/roomdraw
cd ~/workspaces/roomdraw
# 2. Setup and run backend with Podman (not Docker!)
cd backend && cp .env.example .env && nano .env
# Make sure to set the relevant environment variables in the .env file
podman build -t roomdraw-backend .
podman run -d --name roomdraw-backend -p 8000:8000 -v $(pwd):/app roomdraw-backend
# 3. Build and serve frontend with http-server
cd ../frontend && cp .env.example .env && nano .env
# Make sure to set REACT_APP_API_URL to the correct value
npm install && npm run build
npx http-server build -p 3001 &
# 4. Configure Apache proxy (see .htaccess section below)
mkdir -p ~/public_html && nano ~/public_html/.htaccess
# 5. Visit https://www.cs.hmc.edu/~USERNAME/roomdraw/Note: Database setup (table creation, data population) is done locally, not on the server. The server only needs the
.envcredentials to connect to ark.cs.hmc.edu.
HMC's CS department infrastructure:
| Server | Purpose | Notes |
|---|---|---|
knuth.cs.hmc.edu |
Compute server | 64 cores, 512GB RAM, has Podman |
ark.cs.hmc.edu |
PostgreSQL database | Only accessible from CS network |
www.cs.hmc.edu |
Public web server | Your ~/public_html/ served here |
Key constraint: CIS firewall blocks external access to ports 3000/8080 on Knuth. Solution: Apache on www.cs.hmc.edu proxies requests to Knuth.
User's Browser
↓
https://www.cs.hmc.edu/~USERNAME/roomdraw
↓ (Apache proxy)
http://knuth.cs.hmc.edu:3000 (frontend)
↓ (API calls via proxy)
http://knuth.cs.hmc.edu:8080 (backend)
↓
ark.cs.hmc.edu:5432 (database)
Required access:
- CS department account (username@cs.hmc.edu)
- SSH access to knuth.cs.hmc.edu
- PostgreSQL credentials (request from Tom Lam - tomqlam [at] gmail [dot] com)
Software (all pre-installed on Knuth):
- Git, Node.js, npm, Go, Python 3
- Podman (use instead of Docker - Docker requires root)
ssh USERNAME@knuth.cs.hmc.edu
mkdir -p ~/workspaces && cd ~/workspaces
git clone https://github.com/tomqlam/roomdraw.git
cd roomdrawRequest database access - Email tcb [at] cs [dot] hmc [dot] edu for:
- PostgreSQL user account on ark.cs.hmc.edu
- Database name (e.g.,
roomdraw25) - Password
Note: Database setup (running
createAllTables.py,createDorms.py, etc.) is done locally or from a dev machine, not on the server. The server only needs credentials to connect.
-
Configure backend environment:
cd ~/workspaces/roomdraw/backend cp .env.example .env nano .env
Minimum config for testing:
SQL_PASS="[from sysadmin]" SQL_IP="ark.cs.hmc.edu" SQL_USER="[from sysadmin]" SQL_DB_NAME="[from sysadmin]" SQL_PORT="5432" USE_SSL="require" REQUIRE_AUTH="False" # Set "True" for production # Leave BunnyNet/email empty for initial testing
-
Build and run with Podman:
podman build -t roomdraw-backend . podman run -d --name roomdraw-backend -p 8000:8000 -v $(pwd):/app roomdraw-backend
-
Useful Podman commands:
podman ps # Check if running podman logs -f roomdraw-backend # View logs podman restart roomdraw-backend # Restart podman stop roomdraw-backend # Stop podman rm roomdraw-backend # Remove (to rebuild)
-
Configure frontend environment:
cd ~/workspaces/roomdraw/frontend cp .env.example .env nano .env
Set the API URL (replace USERNAME):
REACT_APP_API_URL=https://www.cs.hmc.edu/~USERNAME/roomdraw/api
-
Build and serve with http-server:
npm install npm run build npx http-server build -p 3001 & -
Managing the frontend server:
# Find the process ps aux | grep http-server # Kill it (to restart) pkill -f "http-server build" # Start again cd ~/workspaces/roomdraw/frontend npx http-server build -p 3000 &
-
Create public_html directory:
mkdir -p ~/public_html -
Create .htaccess file (
~/public_html/.htaccess):RewriteEngine On # API proxy - routes to backend on port 8080 RewriteRule "^roomdraw/api/(.*)?$" "http://knuth.cs.hmc.edu:8080/$1" [P,L,QSA] # Add trailing slash if missing RewriteCond %{REQUEST_URI} ^/~USERNAME/roomdraw$ RewriteRule ^(.*[^/])$ $1/ [R=301,L] # Frontend proxy - routes to React app on port 3000 RewriteRule "^roomdraw(.*)$" "http://knuth.cs.hmc.edu:3000/$1" [P] # Error handling ErrorDocument 502 /~USERNAME/maintenance.html ErrorDocument 503 /~USERNAME/maintenance.html ErrorDocument 504 /~USERNAME/maintenance.html
Important: Replace
USERNAMEwith your actual CS username! -
Set permissions:
chmod 755 ~/public_html chmod 644 ~/public_html/.htaccess
-
Create maintenance page (
~/public_html/maintenance.html):<!DOCTYPE html> <html> <head> <title>Maintenance</title> </head> <body style="text-align:center;padding:50px;font-family:sans-serif;"> <h1>🛠️ Under Maintenance</h1> <p>Room Draw is being updated. Check back soon!</p> </body> </html>
- Visit
https://www.cs.hmc.edu/~elli/digitaldraw/ - Check that the page loads and shows dorm data
- If errors occur, check logs:
# Backend logs podman logs -f roomdraw-backend # Check if frontend is running ps aux | grep http-server
cd ~/workspaces/roomdraw
git pull
# If backend code changed, rebuild the image:
cd backend
podman stop roomdraw-backend && podman rm roomdraw-backend
podman build -t roomdraw-backend .
podman run -d --name roomdraw-backend -p 8000:8000 -v $(pwd):/app roomdraw-backend
# If frontend code changed:
cd ../frontend
npm install # If dependencies changed
npm run build
pkill -f "http-server build" # Stop old server
npx http-server build -p 3001 &| Problem | Solution |
|---|---|
| 403 Forbidden | chmod 755 ~/public_html && chmod 644 ~/public_html/.htaccess |
| 502/503/504 Gateway Error | Check if services are running: podman ps and ss -tlnp | grep 3000 |
| Database connection failed | Verify credentials, ensure USE_SSL="require" |
| Frontend stops after disconnect | Run with nohup npx http-server build -p 3000 & or use screen |
| "Permission denied" on pip | Use pip install --user flag |
| Podman build fails | Check Go dependencies, try podman build --no-cache |
If you're running Podman on a server where you need root privileges to build, build the image locally and transfer it:
# 1. Build locally
docker build -t roomdraw-backend .
# 2. Save to tar file
docker save roomdraw-backend > roomdraw-backend.tar
# 3. Transfer to server
scp roomdraw-backend.tar USERNAME@knuth.cs.hmc.edu:~/workspaces/roomdraw/backend/
# 4. Load on server
ssh USERNAME@knuth.cs.hmc.edu
cd ~/workspaces/roomdraw/backend
podman load < roomdraw-backend.tar
# 5. Run as usual
podman run -d --name roomdraw-backend -p 8080:8080 -v $(pwd):/app roomdraw-backendBefore going live for actual Room Draw:
- Database populated with real student data
-
REQUIRE_AUTH="True"in backend .env - BunnyNet CDN configured for suite images
- Email notifications configured
- Apache proxy tested from external network
- Services running in background (http-server with &, podman with -d)
- Tested room pulls, bumps, and priority calculations
- Mobile device testing complete
- Database backup created