{"id":48034291,"url":"https://github.com/jondmarien/ctfd-live-scoreboard","last_synced_at":"2026-04-04T13:58:12.904Z","repository":{"id":276207063,"uuid":"928566190","full_name":"jondmarien/ctfd-live-scoreboard","owner":"jondmarien","description":"Using the CTFd API, we have a Live Scoreboard for our annual ISSessions CTF.","archived":false,"fork":false,"pushed_at":"2026-03-03T00:07:49.000Z","size":16852,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-03T02:08:28.683Z","etag":null,"topics":["ctf","ctf-infrastructure","ctfd","ctfs"],"latest_commit_sha":null,"homepage":"https://iss-ctfd-live-scoreboard.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jondmarien.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"docs/AGENTS.md","dco":null,"cla":null}},"created_at":"2025-02-06T20:58:30.000Z","updated_at":"2026-03-03T00:07:52.000Z","dependencies_parsed_at":"2025-02-06T22:27:00.176Z","dependency_job_id":"f504e22c-faa0-47e3-aaab-542ceb4831c4","html_url":"https://github.com/jondmarien/ctfd-live-scoreboard","commit_stats":null,"previous_names":["jondmarien/ctfd-live-scoreboard"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jondmarien/ctfd-live-scoreboard","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondmarien%2Fctfd-live-scoreboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondmarien%2Fctfd-live-scoreboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondmarien%2Fctfd-live-scoreboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondmarien%2Fctfd-live-scoreboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jondmarien","download_url":"https://codeload.github.com/jondmarien/ctfd-live-scoreboard/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jondmarien%2Fctfd-live-scoreboard/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31402276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ctf","ctf-infrastructure","ctfd","ctfs"],"created_at":"2026-04-04T13:58:12.822Z","updated_at":"2026-04-04T13:58:12.890Z","avatar_url":"https://github.com/jondmarien.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ⚔️ ISSessions Fantasy CTF - Guild Quest Board 🛡️\n\n\u003e *\"The Quest Giver is watching. The rankings await.\"*\n\nA high-fantasy themed live scoreboard for CTFd, built for **ISSessions Fantasy CTF 2026**. Features an animated tavern background with aurora effects, floating fireflies, fog layers, and immersive D\u0026D/Baldur's Gate 3 inspired visuals.\n\n![ISSessions Fantasy CTF](public/img/fantasy-ctf-banner.png)\n\n---\n\n\u003chttps://github.com/user-attachments/assets/a80b40eb-f692-4377-9147-d56b85102945\u003e\n\n## 🏰 Features\n\n### Visuals \u0026 Animations\n\n- **Animated Tavern Background** — Layered WebGL aurora, floating fireflies, drifting fog, and film grain\n- **Click Sparks** — Gold particle effects on every click\n- **Animated Counters** — Scores roll up with smooth number animations\n- **Medieval Aesthetic** — Warm amber, gold, and parchment color scheme\n- **FOUC Prevention** — Page hidden until stylesheets load for a clean first paint\n\n### Scoreboard View\n\n- **Live Rankings** — Adventuring Parties ranked by Gold Pieces (GP)\n- **Expandable Team Cards** — Click a team to see members and their scores\n- **Adventurer Modal** — Click any member to see their quest log, solves by category, and stats\n- **Team Summary Modal** — View full team details including affiliation, country, and website\n\n### Quests View\n\n- **Quest Board** — All challenges grouped by category (realm), sorted by value\n- **Quest Detail Modal** — Click any quest to see description, current/original GP value, solve count, tags, max attempts, and value decay for dynamic challenges\n- **Mock Data Fallback** — Fantasy-themed sample quests displayed before the competition begins\n\n### Guilds View\n\n- **Guild Registry** — Browse all registered guilds with member counts and scores\n- **Adventurer \u0026 Team Modals** — Drill into any guild or member for full details\n\n### Adventurers View\n\n- **Individual Rankings** — Every adventurer ranked by their personal Gold Pieces, derived from scoreboard data\n- **Adventurer Modal** — Click any adventurer for their full quest log and stats\n\n### Changelog (Chronicle of Changes)\n\n- **📜 Scroll Icon** — Access the changelog via the scroll button next to the view selector\n- **Timeline Layout** — A vertical timeline with dates, version badges, and tags\n- **Fantasy Themed** — Styled with the same amber-and-stone palette and medieval fonts as the rest of the board\n- **Full History** — Every major update since the React rebuild documented in rich detail\n\n### General\n\n- **Fantasy Terminology** — Teams are \"Guilds\", points are \"Gold Pieces (GP)\", challenges are \"Quests\", categories are \"Realms\"\n- **Last Scrying Footer** — Shows when data was last refreshed on every view\n- **Auto-refresh** — Scries the CTFd API every 30 seconds with server-side caching\n- **Responsive Design** — Works on guild halls of all sizes (mobile-friendly)\n- **XSS Protected** — All user data sanitized before rendering\n\n## 🛠️ Tech Stack\n\n- **React 19** + TypeScript\n- **Vite 7** — Lightning fast builds\n- **Tailwind CSS 4** — Custom `@theme` with tavern colors\n- **Framer Motion + GSAP** — Smooth animations\n- **Radix UI + shadcn/ui** — Accessible components\n- **Vercel Serverless Functions** — API proxy with Bun runtime\n- **Bun** — Package manager and runtime\n\n## 🗡️ Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/jondmarien/ctfd-live-scoreboard.git\ncd ctfd-live-scoreboard\n\n# Install dependencies\nbun install\n\n# Start dev server (proxies API to CTFd)\nbun run dev\n```\n\nOpen `http://localhost:8000` — the Vite dev server proxies `/api/*` to `issessionsctf.ctfd.io` automatically.\n\n## 🚀 Deployment (Vercel — Recommended)\n\n1. Push the repo to GitHub\n2. Import the project at [vercel.com/new](https://vercel.com/new)\n3. Add environment variables in **Settings → Environment Variables** (see [Configuration](#-configuration))\n4. Deploy — Vercel auto-detects Vite, installs with Bun, and builds\n\nThe included `vercel.json` handles:\n\n- **API proxying** via a catch-all serverless function (`api/[...path].ts`) that injects the auth token server-side\n- **Server-side caching** with `s-maxage=30` and `stale-while-revalidate=60` to reduce polling load\n- **SPA routing** — all non-API routes rewrite to `index.html`\n\n**Custom domain:** Add your domain in Vercel project Settings → Domains, then create a CNAME record pointing to `cname.vercel-dns.com`.\n\n## 🐳 Docker (Deprecated — Supported for Self-Hosting)\n\n\u003e **Note:** Docker deployment is deprecated in favor of Vercel. The Dockerfile is kept for self-hosting scenarios. If using Docker, you'll need to configure the CTFd API token separately (e.g. via nginx proxy headers).\n\n```bash\n# Build locally\ndocker build -t fantasy-ctf-scoreboard .\ndocker run -p 80:80 fantasy-ctf-scoreboard\n```\n\n## 📜 Configuration\n\n| Variable | Required | Description |\n| -------- | -------- | ----------- |\n| `CTFD_API_TOKEN` | Yes | API token for your CTFd instance (private scoreboards) |\n| `WEBHOOK_URL` | Yes | Discord channel webhook URL for First Blood announcements |\n| `WEBHOOK_SECRET` | Yes | CTFd shared secret for webhook validation (Admin → Webhooks) |\n\n**Dev proxy** is configured in `vite.config.ts` — the Vite dev server proxies `/api/*` to `issessionsctf.ctfd.io` automatically. No separate config file needed.\n\n## 🩸 First Blood Discord Webhook\n\nWhen a challenge is solved for the first time, CTFd pushes a **First Blood** event to a Vercel serverless function at `/api/webhook/firstblood`. The function enriches the event with challenge/solver details from the CTFd API and sends a fantasy-themed Discord embed to the configured webhook channel.\n\n### Webhook Setup\n\n1. In CTFd **Admin → Webhooks**, copy the **Shared Secret** → add as `WEBHOOK_SECRET` in Vercel\n2. Add webhook target: `https://\u003cyour-domain\u003e/api/webhook/firstblood`\n3. Select the **First Blood** event type\n4. CTFd validates the endpoint automatically, then pushes events on first solves\n\n## 📁 Project Structure\n\n```tree\nsrc/\n├── components/\n│   ├── animation/              # Reusable animation primitives\n│   │   ├── AnimatedContent.tsx  # Scroll-triggered reveal\n│   │   ├── AnimatedList.tsx     # Staggered list animations\n│   │   ├── ClickSpark.tsx       # Gold particle click effects\n│   │   ├── Counter.tsx          # Animated number counter\n│   │   ├── ShinyText.tsx        # Shimmer text effect\n│   │   └── SplitText.tsx        # Per-character text animation\n│   ├── background/             # Tavern atmosphere layers\n│   │   ├── TavernBackground.tsx # Composition root\n│   │   ├── Aurora.tsx           # WebGL aurora borealis\n│   │   ├── Fireflies.tsx        # Floating particle fireflies\n│   │   ├── Fog.tsx              # Drifting fog layers\n│   │   └── Noise.tsx            # Film grain overlay\n│   ├── modals/                 # Detail modals\n│   │   ├── AdventurerModal.tsx  # Player stats \u0026 quest log\n│   │   ├── QuestModal.tsx       # Challenge details \u0026 description\n│   │   └── TeamSummaryModal.tsx # Full team overview\n│   └── ui/                     # Core UI components\n│       ├── Scoreboard.tsx       # Main container + view switching\n│       ├── ViewSelector.tsx     # Tab bar (Scoreboard / Guilds / Adventurers / Quests) + 📜 changelog button\n│       ├── TeamCard.tsx         # Expandable team row\n│       ├── ChallengesView.tsx   # Quest board grouped by realm\n│       ├── TeamsView.tsx        # Guild registry list\n│       ├── AdventurersView.tsx  # Individual adventurer rankings\n│       ├── ChangelogView.tsx    # Chronicle of Changes timeline\n│       ├── Header.tsx           # Banner + animated title\n│       ├── SpotlightCard.tsx    # Mouse-follow spotlight card\n│       └── StarBorder.tsx       # Animated border effect\n├── hooks/                      # Data fetching \u0026 state\n│   ├── useScoreboard.ts         # Scoreboard data + XSS sanitization\n│   ├── useTeamsList.ts          # Teams list with member details\n│   ├── useChallengeCache.ts     # Challenge cache + mock data fallback\n│   ├── useTeamDetails.ts        # Individual team details\n│   └── useAdventurerDetails.ts  # Individual player details\n├── data/\n│   └── changelog.ts             # Changelog entries (typed array)\n├── lib/\n│   ├── animations.ts            # Shared Framer Motion variants\n│   └── utils.ts                 # Utility functions\n├── App.tsx                      # Root component\n└── main.tsx                     # Entry point\n\napi/                             # Vercel serverless functions (Bun runtime)\n├── [...path].ts                 # Catch-all API proxy → CTFd with auth injection\n└── webhook/\n    └── firstblood.ts            # First Blood → Discord webhook handler\n```\n\n## 🐉 Credits\n\n- **Theme**: ISSessions Fantasy CTF 2026\n- **Developer**: [Jonathan Marien](https://github.com/jondmarien)\n- **API**: [CTFd](https://docs.ctfd.io/docs/api/getting-started/)\n- **Animations**: [Framer Motion](https://motion.dev), [GSAP](https://gsap.com)\n\n---\n\n*Enter the Realm. Accept the Quest. 👁️✨*","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondmarien%2Fctfd-live-scoreboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjondmarien%2Fctfd-live-scoreboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjondmarien%2Fctfd-live-scoreboard/lists"}