Appearance
API Reference
Every server-side endpoint in the ecosystem. All are Cloudflare Pages Functions (file = route) unless noted. Conventions shared by all: JSON in/out, CORS handled, GET on the AI routes is a health check that reports the resolved provider chain without leaking key values, and every AI route degrades to a clearly labelled [echo provider] stub when no key is configured — an honest failure, never a fake answer.
AI grading & tutoring
POST /ai-code-review — four modes in one route
mode | Purpose | Key request fields | Response |
|---|---|---|---|
help | hint for the problem being solved | question, code, language | { reply } (markdown) |
chat | follow-up turns on a help thread | messages[], problem context | { reply } |
ask | the general tutor (AskAiPopover) | subject, topic, messages[{role,text}] | { reply } |
optimize | complexity/critique of a submission | code, language, question | { reply } (structured markdown) |
History is clipped (last N turns, long messages truncated) before prompting; replies are coerced to JSON via coerceJson/firstBalanced because free models love decorating JSON with prose.
POST /grade-concept
Grades a free-text CS-fundamentals answer against its authored rubric. Body: { question, answer, expected, rubric? } → { verdict, score, feedback }. The system prompt forbids quoting the model answer verbatim in feedback (it would leak the answer into the UI). SQL-flavoured concept questions are judged as text — this route never executes SQL.
POST /evaluate-aptitude
AI coaching layer for aptitude: correctness is decided deterministically client-side (aptitudeEval.js); this route only explains. Body: { question, expected, rubric?, solution?, userAnswer } → { feedback }.
POST /grade-sql-practice
Grades SQL practice answers: result-set comparison happens client-side in sql.js; the AI layer reviews query quality/approach. → { verdict, feedback }.
All four import the shared chain from functions/_ai-providers.js — see AI Pipeline.
Code execution
POST /run-code
Judge0 proxy. Body: { language_id, source_code, stdin?, expected_output?, … } (base64 round-tripped). Applies server-side hard caps regardless of what the client asks for:
| Env | Default |
|---|---|
JUDGE0_MAX_CPU_TIME_LIMIT | 15 s |
JUDGE0_MAX_WALL_TIME_LIMIT | 20 s |
JUDGE0_MAX_MEMORY_LIMIT | 512000 KB |
JUDGE0_MAX_STACK_LIMIT | 128000 KB |
Plus JUDGE0_URL, JUDGE0_AUTH_TOKEN. Returns Judge0's verdict payload (status, stdout, time, memory) normalized by the client's judgeRunner.
Content proxies
GET /list-notes?path=… / GET /get-notes?path=…
Proxy GitHub's Contents API into the private Docy repo using server-side GITHUB_TOKEN — directory listing and file body respectively. Exists so the token never ships to the client and Docy can stay private. Missing token → explicit 500 with a "token missing" message, not a silent empty state.
GET /cf-profile?handle=… / GET /cf-status?handle=…
Codeforces proxy (CF has no CORS). cf-profile merges user.info + rating history into one dashboard payload; cf-status returns recent submissions, which CP solve verification scans for OK verdicts. Both back off politely on CF rate limits.
This docs portal
POST /api/ask-docs (lives in this repo, not the website)
The retrieval-grounded docs assistant. Body: { messages[{role,text}], page? } → { reply, sources[{title,path}] }. Ranks the prebuilt index (/ai/docs-map.json), stuffs the top pages as context, answers only from documentation, and returns real source paths (filtered against the index — the model can't invent links). GET = health with the resolved fallback chain. Architecture in AI Pipeline.
Not Functions
Background OA judging and reminder emails are standalone Workers with cron triggers, not request/response endpoints — documented in Cloudflare Workers.