CompComp (Competition Compass) helps students find competitions and programs they can actually join — matched to age, grade, location, format, and interests.
Live site: GitHub Pages frontend + Supabase backend.
- You fill out a short profile (or search for something specific like “Stardance” or “USACO”).
- The app returns up to 10 recommended matches — official competition pages, registration links, Devpost events, etc.
- A second section, “May not be what you're looking for”, shows related listicles, roundups, and close matches that didn’t make the top 10.
You submit the form
↓
Edge Function (discover-competitions)
↓
┌──────────────────────────────────────┐
│ 1. Match from Supabase database │
│ 2. Web search (Serper) if needed │
│ 3. Rule filters (block junk/media) │
│ 4. Optional Gemini AI filter │
│ 5. Return 10 primary + suggested │
└──────────────────────────────────────┘
↓
Cards shown on the page
- Pulls from the database first (7 slots) and adds a few fresh web results (3 slots) when Serper is configured.
- Good web finds are saved to the database so the next search is cheaper.
- Web search runs first to find pages that match the name you typed.
- Database rows are used to fill gaps.
Gemini is not a custom trained model. It’s a one-shot prompt filter:
- The app sends Gemini a numbered list of up to 10 candidates (title, URL, date, snippet).
- The prompt says what to keep (real competition pages) and reject (listicles, forums, news, closed events).
- Gemini replies with JSON like
{"keep":[0, 2, 5]}. - Only those indices stay in the recommended section.
If Gemini is unavailable (no API key, rate limit, daily quota), the app uses rule-based filters instead. If Gemini rejects everything, the rule-filtered results are kept so you don’t get zero cards.
Gemini quota: about 15 calls/day, spaced apart, to stay within the free tier.
| Layer | Tech |
|---|---|
| Frontend | HTML, CSS, JavaScript (GitHub Pages) |
| Database | Supabase (competitions table) |
| Backend | Supabase Edge Function (discover-competitions, Deno/TypeScript) |
| Web search | Serper |
| AI filter | Google Gemini (gemini-2.0-flash-lite) |
| Deploy | GitHub Actions → Supabase Edge Functions |
index.html Landing page + form
styles.css UI styles
script.js Form handling, card rendering
config.js Supabase URL + publishable key (browser-safe)
matching.js Client-side fallback matching if Edge Function fails
supabase/
functions/
discover-competitions/ Main discovery API
_shared/ Matching, dates, Gemini filter, images
migrations/ SQL migrations for the competitions table
.github/workflows/ Auto-deploy Edge Function on push to main
DEPLOY.md Detailed setup guide
See DEPLOY.md for the full walkthrough. Short version:
- Supabase — run migrations in
supabase/migrations/andsupabase-rls.sql. - GitHub secrets —
SUPABASE_ACCESS_TOKEN,SUPABASE_PROJECT_REF(for auto-deploy). - Edge Function secrets (Supabase Dashboard → Edge Functions → Secrets):
SERPER_API_KEY— web search (recommended)GEMINI_API_KEY— optional AI filtering
Update config.js with your Supabase project URL and publishable key. Never put service-role or secret keys in the frontend.
No build step. Open index.html in a browser or serve the folder statically:
python3 -m http.server 8080Then visit http://localhost:8080. Discovery requires the deployed Edge Function (or Supabase local stack if you set that up separately).
Hackathon / student project — check with the repo owner for reuse terms.