ChartGPT #
AI model performance vs price comparison tool. Scatter plot of Humanity's Last Exam scores against price per million tokens, with interactive filters.
Built with Fresh v2 — Deno's full-stack web framework.
Stack #
| Layer | What |
|---|---|
| Runtime | Deno 2.9+ |
| Framework | Fresh v2 (file-based routing, islands) |
| UI | Preact + @preact/signals |
| Chart | Chart.js v4 (canvas scatter) |
| CSS | Tailwind v4 |
| Desktop | deno desktop (built-in, no install) |
| Test | Deno built-in test runner + @std/expect |
Quick start #
deno task dev # Vite dev server with HMR
Open http://localhost:5173 — redirects to /compare.
Commands #
| Command | What |
|---|---|
deno task dev |
Vite dev server with HMR |
deno task build |
Production build to _fresh/ |
deno task start |
Serve production build |
deno task check |
Format + lint + type-check |
deno task test |
Run all tests |
deno task desktop |
Build desktop binary (run build first) |
deno task desktop-dev |
Desktop app with HMR |
deno fmt |
Auto-format |
deno lint |
Lint |
just github-push |
Push to GitHub (triggers CF Worker deploy) |
Data format #
Supply your own JSON array via Paste JSON button or drag-and-drop a .json
file:
[
{
"name": "GPT-5.6 Sol",
"provider": "OpenAI (US)",
"performance": 43.1,
"price_per_million_tokens_in_out": [5.00, 30.00],
"category": "Frontier Flagship / Reasoning",
"released": "2026-07-09"
}
]
| Field | Type | Description |
|---|---|---|
name |
string | Model name (shown on plot) |
provider |
string | Company name (colors the dot) |
performance |
number | Humanity's Last Exam score (%) |
price_per_million_tokens_in_out |
[number, number] | [input_price, output_price] |
category |
string | Model category / tier |
released |
string | Release date YYYY-MM-DD |
A demo dataset is pre-loaded with 6 models.
Controls #
- Models per provider — limits how many recent models each provider shows
- Price (Input / Output) — toggles Y axis between input and output token pricing
- Scale (Log / Linear) — toggles Y axis scale
- Data (Paste JSON) — paste your own dataset
Desktop app #
Fresh 2.x is auto-detected by deno desktop (built into Deno 2.9+):
deno task build
deno task desktop # production desktop binary
deno task desktop-dev # dev mode with HMR
The binary bundles your code, the Deno runtime, and a webview renderer into a
single executable. Output is in chartGPT/.
Cloudflare Workers #
Push to GitHub — Cloudflare picks it up, builds, and deploys:
just github-push
What Cloudflare runs on its end:
Build: npx deno install --allow-scripts=npm:sharp,npm:workerd && npx deno task build
Deploy: npx wrangler deploy
Key files:
server.js— Worker entry, imports_fresh/server/server-entry.mjs, exports{ fetch: server.fetch }wrangler.jsonc— Config withmain: "./server.js", assets at_fresh/client
Gotchas:
Deno.readTextFilebreaks in Workers — useimport ... with { type: "json" }instead@cloudflare/vite-pluginconflicts with Fresh SSR build order — wrangler direct is the working path
Tests #
deno task test
Tests cover: data integrity, price extraction, filtering logic (N-most-recent
per provider), and entry validation — all pure functions in utils/compare.ts.
Architecture #
routes/
compare.tsx — chart page (loads demo data, renders island)
index.tsx — redirects to /compare
islands/
CompareChart.tsx — interactive chart island (Chart.js canvas)
components/
Button.tsx — shared UI primitives
utils/
compare.ts — shared types & pure functions
tests/
compare_test.ts — tests
assets/
styles.css — Tailwind v4 + Geist font import
static/
demo-models.json — default dataset