Language: English | 繁體中文
AI Arena is a static gallery for comparing outputs from different AI models and thinking-effort settings on the same task.
The site is pure HTML, CSS, and JavaScript, so it can be deployed directly to GitHub Pages without a backend. The homepage is provider-neutral; OpenAI, Anthropic, Google, xAI, GLM, DeepSeek, Kimi, and other providers are represented through submission metadata.
Want to contribute an AI-generated result? See CONTRIBUTING.md. Traditional Chinese contribution notes are available in CONTRIBUTING.zh-TW.md.
You do not need to edit the homepage or manually maintain tasks.json when adding a submission:
- Put the generated output in
tasks/<task-id>/<submission-id>/. - Add a
submission.jsonfile in the same folder. - Run
node scripts/build-manifest.mjsto regeneratetasks.json. - Commit and push the output plus the regenerated manifest. GitHub Actions validates the manifest and deploys the site.
For local preview:
node scripts/build-manifest.mjs
python3 -m http.server 8000
# Open http://localhost:8000tasks.json is generated. Commit it, but do not edit it by hand.
.
|-- index.html
|-- tasks.json # generated
|-- scripts/
| `-- build-manifest.mjs
|-- assets/
| |-- app.js
| `-- style.css
`-- tasks/
`-- <task-id>/
|-- task.json # shared task metadata
`-- <submission-id>/
|-- submission.json # model, effort, runtime metadata
`-- index.html # generated output
Example submission:
tasks/spinning-cube/openai-gpt-high/
|-- index.html
`-- submission.json
submission.json:
{
"provider": "openai",
"model": "GPT",
"modelId": "<exact model ID returned by the API>",
"effort": "high",
"client": "codex",
"author": "<your GitHub handle>",
"generatedAt": "2026-06-07T12:00:00Z",
"metrics": {
"durationMs": 42000,
"inputTokens": 1200,
"outputTokens": 8400,
"cachedInputTokens": 0
},
"order": 30
}client is the tool used to generate the output, such as claude-code, codex, opencode, kiro, cursor, or api. generatedAt is rendered in UTC before the GitHub author link, for example 2026-07-02 18:00 @F-e-u-e-r. See CONTRIBUTING.md for metrics and cost details.
You can include additional metadata for comparison or future filtering:
{
"provider": "google",
"model": "Gemini",
"modelId": "<exact-model-id>",
"effort": "high",
"temperature": 0.7,
"seed": 42,
"tools": [],
"attempt": 1
}The manifest builder preserves extra fields.
effort is a free-form string. high, medium, and low have dedicated badge colors; other values still render with the default badge style.
Each card shows four comparable values: time, input tokens, output tokens, and cost. Missing values are displayed as a dash. You do not need to calculate cost yourself: build-manifest.mjs uses data/pricing.json plus the token counts in submission.json to generate costUsd.
data/pricing.jsonis keyed bymodelId. Prices are in USD per 1 million tokens. UpdatesourceandverifiedAtwhen changing prices.- If a
modelIdis not in the pricing file, cost is shown as a dash. Add that model's pricing in the same PR if possible. - Claude Code users can run
node scripts/metrics-from-claude-code.mjs <session.jsonl>to generate a ready-to-pastemetricsblock.
Security note: files under tasks/, task.json, submission.json, and regular assets are published as public website content. Do not commit API keys, tokens, .env files, private prompts, internal logs, or other sensitive data.
Create tasks/<task-id>/task.json:
{
"title": "My task",
"type": "iframe",
"runtime": "webgl",
"prompt": "The original prompt sent to the model...",
"description": "What this task is comparing.",
"order": 30
}Recommended runtime values:
| runtime | Use case |
|---|---|
canvas |
Native HTML, JavaScript, and Canvas |
webgl |
Three.js or WebGL |
unity |
Unity WebGL builds |
static |
Images, videos, or other static outputs |
Set type at the task level as the default, or override it in submission.json.
| type | Use case | submission fields |
|---|---|---|
iframe |
HTML, Three.js, JavaScript, Unity | Defaults to index.html in the submission folder |
image |
Static render output | src |
video |
Animation or recording | src, optional poster |
model-viewer |
Interactive .glb or .gltf model |
src, optional poster |
Media paths are resolved relative to the submission.json file. Example:
{
"provider": "deepseek",
"model": "DeepSeek",
"modelId": "<exact-model-id>",
"type": "image",
"src": "render.png"
}External media must use https: URLs. http:, data:, blob:, and other protocols are rejected by the manifest builder.
The repository includes .github/workflows/pages.yml and is configured to deploy with GitHub Actions. If the Pages settings ever need to be recreated, use:
- Repository Settings -> Pages.
- Build and deployment -> Source -> GitHub Actions.
- Push to
main.
The workflow validates metadata, confirms that tasks.json is current, scans for obvious secrets, and deploys the static site.
- GitHub blocks regular repository files larger than 100 MiB. GitHub Pages does not support Git LFS, so large builds should use Cloudflare Pages or object storage.
- Unity Brotli or Gzip builds require correct
Content-Encodingheaders. GitHub Pages does not support custom headers, so enable Unity's Decompression Fallback, disable compression, or use hosting that supports custom headers. - The current iframe sandbox is suitable for single-file HTML, Three.js, and Canvas outputs. Unity or multi-file ES module submissions may need a separate hosting/origin decision later.