A gamified, competitive training platform for career preparation — think Chess.com meets LeetCode for the interview process. Candidates enter pathway-specific arenas (Investment Banking, Quant, Software Engineering, Consulting, and more), compete in timed 1‑v‑1 challenge "mechanics," and earn skill‑based ratings scored by a calibrated multi‑judge AI ensemble — with full replays, a skill tree, quests, and cohort leaderboards.
Under the hood, it's equally a candidate‑benchmarking and ranking engine: every attempt is converted into calibrated, multi‑dimensional ratings, so the same system that trains candidates also ranks them within a cohort — structured evaluation signal instead of a static CV.
Ascendra began at QuantiHack, a hackathon run by Jane Street and Optiver. I qualified for the finals by placing in the daily top‑10 of the week‑long algorithmic trading competition that gated it — top 10 out of 850+ participants. The finals were a build‑in‑a‑day sprint, which produced the first working MVP. Since then I've kept building it out well beyond the hackathon scope: a re‑architected backend, a full second‑generation frontend, a durable AI scoring pipeline, and a growing catalogue of domain‑specific challenges.
This repo is that ongoing work. It is intentionally organised so someone new (or a
future me) can pick it up and keep going — see docs/REPO_TOUR.md.
- Pathway‑specific arenas. Each career pathway (
software_engineering,quant,investment_banking,consulting,product,law,graduate_schemes) has its own challenge catalogue, rating weights, and cohort taxonomy. - 1‑v‑1 challenge mechanics. 20 live mechanics — LeetCode drills, system‑design rooms, behavioural duels, CV battles, mental‑maths blitzes, paper‑LBO speed runs, DCF walkthroughs, case‑lite interviews, market‑sizing, probability/Bayesian puzzles, options intuition, and more.
- Three independent skill arenas. Every attempt is scored across
profile,professional, andtechnicalarenas, each with its own Elo. A weighted Overall Domain Elo rolls them up using per‑pathway weights. - Calibrated multi‑judge AI scoring. A 9‑step durable pipeline runs an ensemble of specialised judges (rubric, pairwise‑preference, deterministic‑numeric, code‑exec, transcript‑analysis) aggregated by a meta‑judge, anchored to recruiter‑style calibration exemplars — not a single naive LLM call.
- Replays, skill tree, quests, leaderboards. Every completed attempt produces a replay artifact; a rule‑based skill tree recommends repair paths; quests and cohort‑aware leaderboards drive engagement.
- Ranked / unranked / practice modes with honest Elo rules (practice never moves rating; boss‑battle "benchmark packs" are intentionally non‑Elo in the MVP).
A two‑frontend monorepo over a bounded‑context FastAPI backend, with durable scoring offloaded to a Vercel Workflow.
flowchart TD
subgraph Client
FV2["frontend-v2<br/>Next.js 16 · Tailwind v4 · shadcn"]
FMVP["frontend<br/>Next.js 14 (MVP, maintenance)"]
end
subgraph Auth
SB["Supabase Auth<br/>(JWT / JWKS)"]
end
subgraph Backend["FastAPI backend — 14 bounded contexts"]
API["Thin routers → services → models → schemas"]
PIPE["Scoring pipeline<br/>(9 steps, multi-judge ensemble)"]
end
subgraph Data
PG[("Supabase Postgres")]
end
subgraph Workers
WF["Vercel Workflow<br/>(durable scoring)"]
LLM["LLM providers<br/>Gemini (dev) · Claude (prod)"]
end
FV2 -->|Bearer JWT| API
FMVP -->|Bearer JWT| API
FV2 -.session.-> SB
API -->|verify JWT| SB
API --> PG
API -->|WORKFLOW_ENABLED=true| WF
WF -->|HMAC-signed callbacks| API
API --> PIPE
PIPE --> LLM
PIPE --> PG
Scoring runs two ways from one codebase: in development the 9 steps run in‑process;
in production the request path persists the submission + early integrity flags, then
enqueues a durable Vercel Workflow that drives the remaining steps via HMAC‑gated
/internal/workflow/* callbacks. See
docs/architecture/scoring-engine.md.
| Layer | Technologies |
|---|---|
| Backend | FastAPI, SQLAlchemy 2, Alembic, Pydantic v2, uv, Python 3.14 |
| Frontend (v2) | Next.js 16 (App Router), TypeScript, Tailwind v4, shadcn/ui, TanStack Query, Supabase SSR, Sentry |
| Frontend (MVP) | Next.js 14, React 18, Tailwind 3, Framer Motion |
| Data / Auth | Supabase Postgres (session pooler), Supabase Auth (JWT verification) |
| AI scoring | Multi‑judge ensemble; Google Gemini (dev) / Anthropic Claude (prod) via direct SDKs; calibration anchors |
| Async / infra | Vercel Workflow (durable scoring), Vercel Sandbox (code exec), HMAC‑gated internal API |
| Quality | pytest (SQLite in‑memory), Vitest, Playwright (a11y + visual + smoke), ruff, ESLint, GitHub Actions CI |
backend/ FastAPI app organised into 14 bounded contexts (ADR 0008)
frontend-v2/ Next.js 16 rebuild — the active frontend
frontend/ Next.js 14 MVP — in maintenance until v2 reaches parity (ADR 0007)
infra/ Vercel Workflow TS project for durable scoring
docs/ ADRs, architecture deep-dives, plans, and specs
scripts/ Env health-check + OpenAPI type codegen
Full map: docs/REPO_TOUR.md.
Requires: Python 3.14 + uv, Node 20+, and a
Supabase project (for Postgres + Auth). Detailed backend setup lives in
backend/README.md.
cd backend
cp .env.example .env # set DATABASE_URL (Supabase session pooler), SUPABASE_URL, SUPABASE_JWT_AUDIENCE
uv sync # install deps
uv run alembic upgrade head # apply schema
uv run python scripts/seed_reference_data.py # seed skill nodes, templates, packs, quests
uv run uvicorn app.main:app --reload # API on :8000, docs at /docsNo LLM keys? Scoring falls back to a deterministic stub automatically — clone, migrate, seed, run.
cd frontend-v2
cp .env.local.example .env.local # NEXT_PUBLIC_SUPABASE_URL/ANON_KEY, NEXT_PUBLIC_API_URL
npm install
npm run dev # app on :3000Leaving NEXT_PUBLIC_API_URL unset (or NEXT_PUBLIC_USE_MOCKS=true) runs the frontend
against rich in‑repo mocks — no backend required to explore the UI.
Both suites are green: 483 backend tests (pytest) and 368 frontend‑v2 tests (Vitest), plus Playwright a11y/visual/smoke specs — all wired into GitHub Actions CI.
# Backend — pytest against an in-memory SQLite fixture (no external DB needed)
cd backend && uv run pytest && uv run ruff check app tests scripts
# Frontend v2 — Vitest unit/component + Playwright a11y/visual/smoke
cd frontend-v2 && npm test && npm run lint| Doc | What |
|---|---|
docs/REPO_TOUR.md |
One‑page map of the codebase |
docs/adr/ |
Architecture Decision Records — the locked‑in decisions and their rationale |
docs/architecture/scoring-engine.md |
The multi‑judge scoring pipeline in depth |
docs/architecture/contexts.md |
The 14 backend bounded contexts |
docs/superpowers/plans/2026-05-14-ascendra-v2-master-plan.md |
The strategic MVP→product roadmap |
docs/AI_WORKFLOW.md |
How this repo uses AI‑assisted, spec‑driven development |
The MVP shipped at the hackathon. Since then the codebase has moved through a phased v2
build: a bounded‑context backend, the durable multi‑judge scoring pipeline, a
second‑generation Next.js 16 frontend with a design‑token system, 20 live challenge
mechanics across four pathways, and a skill‑tree progression system. frontend-v2 is
the active frontend; the original frontend/ MVP stays in maintenance until v2 reaches
parity and the cutover happens (ADR 0007).
Ascendra is developed with an AI‑assisted, human‑directed, spec‑driven workflow —
design → ADR → test‑first plan → implement → verify. That process is documented, along
with where its artifacts live, in docs/AI_WORKFLOW.md.
MIT © 2026 Muhammad Taha