A UW Blueprint x BobaTalks project that automates the Flowers tradition โ letting students celebrate wins through a Discord bot and displaying approved posts on the BobaTalks website.
This project includes:
- Discord Bot โ Collects "Flowers" submissions and handles moderation.
- Web App (Next.js) โ Displays approved Flowers on the BobaTalks site.
- Database (Supabase) โ Stores submissions and approvals securely.
- CI/CD โ Enforces code quality and consistency through GitHub Actions.
| Layer | Technology |
|---|---|
| Bot | Node.js + TypeScript + discord.js |
| Web | Next.js 15 + Tailwind CSS |
| Database | Supabase (PostgreSQL) |
| CI/CD | GitHub Actions |
| Code Quality | ESLint, Prettier, Husky, TypeScript strict mode |
| Check | Command | Expected Result |
|---|---|---|
| Node.js installed | node -v |
โฅ 22.x |
| npm installed | npm -v |
shows a version number |
| Dependencies installed | npm ci |
completes without errors |
| Linting passes | npm run lint |
no errors or warnings |
| Formatting passes | npm run format -- --check . |
no changed files |
| TypeScript clean | npx tsc --noEmit |
no type errors |
| Precommit works | git commit -m "test: husky check" |
runs precommit checks automatically |
git clone https://github.com/uwblueprint/bobatalks-flowers.git
cd bobatalks-flowersnpm cicp .env.example .envFill in the placeholder values
npm run lint
npm run format -- --check .
npx tsc --noEmitIf these three pass, your setup is perfect โ .
We use Husky + lint-staged to enforce formatting before commits.
Test it:
git add .
git commit -m "test: check husky hook"Expected: Prettier and ESLint run automatically before committing.
If hooks donโt run:
npx husky installEvery push and PR triggers GitHub Actions to run:
- โ
Linting (
npm run lint) - โ
Formatting check (
npm run format -- --check .) - โ
TypeScript check (
npx tsc --noEmit)
PRs canโt be merged unless these checks pass.
To simulate CI locally:
npm ci
npm run lint
npm run format -- --check .
npx tsc --noEmit| Issue | Fix |
|---|---|
| ESLint errors | npm run lint --fix |
| Prettier issues | npm run format |
| Husky hook not running | npx husky install |
| TypeScript โNo inputs foundโ | Create a src/ folder or place .ts files at root |
-
Create a new branch:
git checkout -b feature/your-feature-name
-
Commit using Conventional Commits:
feat:โ new featurefix:โ bug fixchore:โ tooling / configs
-
Push and open a PR โ CI must pass before merging.
| Command | Description |
|---|---|
npm run lint |
Run ESLint |
npm run format |
Format with Prettier |
npm run format -- --check . |
Check Prettier formatting (read-only) |
npx tsc --noEmit |
Type-check only |
npx husky install |
Reinstall Git hooks |
npm run dev |
Run Discord bot in dev mode |
npm run build |
Build TypeScript to JavaScript |
npm run register |
Register Discord slash commands |
npm start |
Run built Discord bot |
The Discord bot code is located in src/bot/. See src/bot/README.md for detailed bot documentation.
The bot auto-deploys daily at 4 AM Toronto time (9 AM UTC) via GitHub Actions.
1. Add GitHub Secrets (Settings โ Secrets and variables โ Actions):
EC2_HOSTโ Your EC2 IP addressEC2_SSH_KEYโ Your entire.pemfile contents
2. Setup EC2 (one-time):
ssh -i your-key.pem ubuntu@your-ec2-ip
# Install Node.js 20 & PM2
sudo apt-get update
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install -g pm2
# Setup project
mkdir -p ~/bobatalks/logs
cd ~/bobatalks
# Create .env file
nano .env
# Add: DISCORD_TOKEN=... and DISCORD_CLIENT_ID=...
# Enable PM2 on boot
pm2 startup systemd -u ubuntu --hp /home/ubuntu
# Run the sudo command that PM2 prints3. Deploy:
- Auto: Pushes to
maindeploy at 4 AM daily - Manual: GitHub โ Actions โ "Deploy BobaTalks" โ Run workflow
4. Register commands (after first deploy):
ssh -i your-key.pem ubuntu@your-ec2-ip
cd ~/bobatalks
node dist/bot/registerCommands.js
pm2 logs bobatalkspm2 status # Check status
pm2 logs bobatalks # View logs
pm2 restart bobatalks # Restart
pm2 reload bobatalks # Zero-downtime reload๐ก Run this one-liner to confirm everything works:
npm run lint && npm run format -- --check . && npx tsc --noEmitโ If you see no output โ congrats, your setup is perfect!