Community model leaderboard
Daily pixel-art image posted to #dev-community-models ranking community text
models by tokens served in the last 24h, with a speed panel and per-model
success badges. Generated by
operations/community-monitor/leaderboard/build-leaderboard.mjs, run
automatically by the community-monitor EC2 agent's CYCLE.md duty 3b (once/day,
~12:00 UTC).
Regenerating manually
cd operations/community-monitor/leaderboard
TB_TOKEN=<token> node build-leaderboard.mjs --dry-run # preview HTML only, no render/upload
TB_TOKEN=<token> POLLI_TOKEN=<token> node build-leaderboard.mjs # full render + upload, prints markdown
--dry-run writes /tmp/leaderboard-preview.html and skips chromium/upload —
use it to sanity-check the Tinybird query and ranking without spending an
upload. The real run only works where chromium and python3-pil are
installed (currently just the community-monitor box — see Rendering below).
Design decisions (read before changing anything)
These came out of several rounds of live feedback — don't relitigate them
without a reason:
- Ranked by tokens served, not request count. Request count rewards
chatty small-completion models over models doing real work. A model with
4× the requests but 1/3 the tokens should NOT outrank the token leader —
this was the single most important correction during design.
- Tokens are the headline number, both as a hero counter at the top
(
57,468,899 TOKENS · 24H) and as the leading column on every row —
deliberately placed before the model name, not after, so the eye reads
magnitude first.
- Stability is a per-row badge, not its own leaderboard. An early
version had a separate "most stable" panel; killed because most models sit
at or near 100% and ties make the ranking meaningless. Now it's a status
indicator only: a lime
PERFECT badge at exactly 100%, pixel hearts (♥♥♥
≥99%, ♥♥ ≥95%, ♥ ≥80%) below that, a skull below 80%. The PERFECT badge
matters — celebrate the models that never failed, don't just lump them
into a heart tier.
- Speed gets its own small panel below the main board (median
tokens/sec, not mean — outliers from cold starts/timeouts skew the mean
badly), not mixed into the main ranking. Top 3 by speed, gold card for
#1.
- Minimal text, maximal graphic. No paragraph explaining the board —
headline number, column headers, bars. If you're tempted to add
explanatory prose, add a stat instead.
- No avatars/rank badges in the main leaderboard board (kept for the
companion "Arena" scatter concept, not the primary board) — a crown on
the #1 row is enough ceremony.
Brand system
- Fonts: Press Start 2P (headings/scores, pixel/arcade feel) + IBM Plex
Mono (body/labels). Both embedded as base64 data-URI
@font-face in
fonts-embedded.css — required, not optional. This board is designed
to render standalone via chromium screenshot, which has no network access
to Google Fonts inside the sandboxed render; without embedding, text
silently falls back to a generic mono and looks broken. If you ever see a
render with non-blocky headings, check the font embed first.
- Regenerating
fonts-embedded.css if a font ever needs to change: fetch
the woff2 from https://fonts.googleapis.com/css2?family=<name> (a
normal browser UA is required — the default curl UA gets served an old
ttf format), base64-encode each src: url(...) and inline it as a data
URI in a @font-face block. Keep it to the Latin subset only — full
Unicode coverage bloats the file for zero benefit on an English-only
board.
- Palette (validated against the
dataviz skill's accessibility
checks): cream #F3EBDE background, ink #110518 text/borders, hard
offset box-shadows (6px 6px 0 #110518, zero border-radius — this is the
house pixel/arcade look, see pollinations.ai/src/ui/components/TopContributors.tsx
for the same vocabulary used elsewhere in the product). Chart-legal
categorical hues derived from brand colors via same-hue OKLCH adjustment
(not the raw brand pastels, which fail contrast/CVD checks): periwinkle
#5978df (speed bars), lavender #8338b3, mint/status-stable #3b9736,
status-watch #b8860b, status-degraded #b03a2e.
- Layout: fixed 1200px width (Discord embed width), height determined by
content (10 rows + speed panel), cropped post-render — see Rendering.
Rendering (chromium on the community-monitor box)
No headless-browser npm dependency (puppeteer, playwright) — the box runs
the chromium snap directly via execFileSync, screenshotting a local HTML
file. Constraints discovered the hard way, all already handled in
build-leaderboard.mjs:
--no-sandbox is required — snap confinement blocks the normal
Chrome sandbox.
- Never write chromium's output into a dot-prefixed directory (e.g.
/home/ubuntu/.foo/) — snap's AppArmor profile silently denies the write
with Permission denied, even though the directory is otherwise
writable by the same user. Use a plain directory name.
- Chromium's CLI has no "screenshot sized to content" mode — it always
renders at the requested
--window-size and leaves trailing whitespace
if the page is shorter. The script renders tall (1200×1600) and crops
the whitespace with a small PIL script (scans for the last row containing
dark pixels). This needs python3-pil installed
(sudo apt-get install -y python3-pil, one-time system package — not a
per-run dependency, and not bundled with the base box image).
- dbus/AppArmor
ERROR lines in stderr during the render (ListActivatableNames,
UPower) are cosmetic sandbox noise, not failures — ignore them; only a
missing output file means the render actually failed.
Uploading and posting
Upload goes straight to the media API (POST https://media.pollinations.ai/upload,
bearer $POLLI_TOKEN, multipart file field) rather than shelling out to the
polli CLI — the CLI isn't installed on the community-monitor box, and the
upload is a two-line fetch, not worth adding a dependency for. See
packages/polli-cli/src/commands/upload.ts if the media API response shape
ever changes.
The generator's stdout JSON includes a ready-to-post markdown field — the
CYCLE.md daily duty posts it verbatim as a single Discord message (the image
URL is inline in the text, Discord auto-embeds it). Don't re-derive or
paraphrase the markdown; the awards it calls out (workhorse by request
count, flawless-100% count, speed crown) are deliberately chosen to surface
stats the image itself doesn't show.
Companion design: "The Arena"
A second visualization (speed × success × price, avatar markers sized
uniformly, price tag per model) was explored alongside the main leaderboard
and posted once as a one-off — its HTML/build script live only in session
scratchpads, not yet promoted into this directory. If asked to make it a
recurring post too, port design-arena-v2.html's structure (GitHub avatar
thumbnails via https://github.com/<user>.png?size=96, pixelated via
nearest-neighbor resize, log-scaled x-axis, piecewise y-axis for the
95–100% success cluster, a simple pairwise-repulsion layout pass so
same-size markers don't overlap) following the same rendering/upload
pipeline as the main board.
1---2name: community-leaderboard3description: Generate and post the daily community-model leaderboard image to Discord. Use when asked to build, regenerate, redesign, or post the community model leaderboard, or when extending its design (e.g. new stat panels, palette changes).4---56# Community model leaderboard78Daily pixel-art image posted to #dev-community-models ranking community text9models by tokens served in the last 24h, with a speed panel and per-model10success badges. Generated by11`operations/community-monitor/leaderboard/build-leaderboard.mjs`, run12automatically by the community-monitor EC2 agent's CYCLE.md duty 3b (once/day,13~12:00 UTC).1415## Regenerating manually1617```bash18cd operations/community-monitor/leaderboard19TB_TOKEN=<token> node build-leaderboard.mjs --dry-run # preview HTML only, no render/upload20TB_TOKEN=<token> POLLI_TOKEN=<token> node build-leaderboard.mjs # full render + upload, prints markdown21```2223`--dry-run` writes `/tmp/leaderboard-preview.html` and skips chromium/upload —24use it to sanity-check the Tinybird query and ranking without spending an25upload. The real run only works where `chromium` and `python3-pil` are26installed (currently just the community-monitor box — see Rendering below).2728## Design decisions (read before changing anything)2930These came out of several rounds of live feedback — don't relitigate them31without a reason:3233- **Ranked by tokens served, not request count.** Request count rewards34 chatty small-completion models over models doing real work. A model with35 4× the requests but 1/3 the tokens should NOT outrank the token leader —36 this was the single most important correction during design.37- **Tokens are the headline number**, both as a hero counter at the top38 (`57,468,899 TOKENS · 24H`) and as the leading column on every row —39 deliberately placed *before* the model name, not after, so the eye reads40 magnitude first.41- **Stability is a per-row badge, not its own leaderboard.** An early42 version had a separate "most stable" panel; killed because most models sit43 at or near 100% and ties make the ranking meaningless. Now it's a status44 indicator only: a lime `PERFECT` badge at exactly 100%, pixel hearts (♥♥♥45 ≥99%, ♥♥ ≥95%, ♥ ≥80%) below that, a skull below 80%. The PERFECT badge46 matters — celebrate the models that never failed, don't just lump them47 into a heart tier.48- **Speed gets its own small panel below the main board** (median49 tokens/sec, not mean — outliers from cold starts/timeouts skew the mean50 badly), not mixed into the main ranking. Top 3 by speed, gold card for51 #1.52- **Minimal text, maximal graphic.** No paragraph explaining the board —53 headline number, column headers, bars. If you're tempted to add54 explanatory prose, add a stat instead.55- **No avatars/rank badges in the main leaderboard board** (kept for the56 companion "Arena" scatter concept, not the primary board) — a crown on57 the #1 row is enough ceremony.5859## Brand system6061- **Fonts**: Press Start 2P (headings/scores, pixel/arcade feel) + IBM Plex62 Mono (body/labels). Both embedded as base64 data-URI `@font-face` in63 `fonts-embedded.css` — **required**, not optional. This board is designed64 to render standalone via chromium screenshot, which has no network access65 to Google Fonts inside the sandboxed render; without embedding, text66 silently falls back to a generic mono and looks broken. If you ever see a67 render with non-blocky headings, check the font embed first.68 - Regenerating `fonts-embedded.css` if a font ever needs to change: fetch69 the woff2 from `https://fonts.googleapis.com/css2?family=<name>` (a70 normal browser UA is required — the default curl UA gets served an old71 ttf format), base64-encode each `src: url(...)` and inline it as a data72 URI in a `@font-face` block. Keep it to the Latin subset only — full73 Unicode coverage bloats the file for zero benefit on an English-only74 board.75- **Palette** (validated against the `dataviz` skill's accessibility76 checks): cream `#F3EBDE` background, ink `#110518` text/borders, hard77 offset box-shadows (`6px 6px 0 #110518`, zero border-radius — this is the78 house pixel/arcade look, see `pollinations.ai/src/ui/components/TopContributors.tsx`79 for the same vocabulary used elsewhere in the product). Chart-legal80 categorical hues derived from brand colors via same-hue OKLCH adjustment81 (not the raw brand pastels, which fail contrast/CVD checks): periwinkle82 `#5978df` (speed bars), lavender `#8338b3`, mint/status-stable `#3b9736`,83 status-watch `#b8860b`, status-degraded `#b03a2e`.84- **Layout**: fixed 1200px width (Discord embed width), height determined by85 content (10 rows + speed panel), cropped post-render — see Rendering.8687## Rendering (chromium on the community-monitor box)8889No headless-browser npm dependency (puppeteer, playwright) — the box runs90the `chromium` snap directly via `execFileSync`, screenshotting a local HTML91file. Constraints discovered the hard way, all already handled in92`build-leaderboard.mjs`:9394- **`--no-sandbox` is required** — snap confinement blocks the normal95 Chrome sandbox.96- **Never write chromium's output into a dot-prefixed directory** (e.g.97 `/home/ubuntu/.foo/`) — snap's AppArmor profile silently denies the write98 with `Permission denied`, even though the directory is otherwise99 writable by the same user. Use a plain directory name.100- **Chromium's CLI has no "screenshot sized to content" mode** — it always101 renders at the requested `--window-size` and leaves trailing whitespace102 if the page is shorter. The script renders tall (1200×1600) and crops103 the whitespace with a small PIL script (scans for the last row containing104 dark pixels). This needs `python3-pil` installed105 (`sudo apt-get install -y python3-pil`, one-time system package — not a106 per-run dependency, and not bundled with the base box image).107- dbus/AppArmor `ERROR` lines in stderr during the render (`ListActivatableNames`,108 `UPower`) are cosmetic sandbox noise, not failures — ignore them; only a109 missing output file means the render actually failed.110111## Uploading and posting112113Upload goes straight to the media API (`POST https://media.pollinations.ai/upload`,114bearer `$POLLI_TOKEN`, multipart `file` field) rather than shelling out to the115`polli` CLI — the CLI isn't installed on the community-monitor box, and the116upload is a two-line `fetch`, not worth adding a dependency for. See117`packages/polli-cli/src/commands/upload.ts` if the media API response shape118ever changes.119120The generator's stdout JSON includes a ready-to-post `markdown` field — the121CYCLE.md daily duty posts it verbatim as a single Discord message (the image122URL is inline in the text, Discord auto-embeds it). Don't re-derive or123paraphrase the markdown; the awards it calls out (workhorse by request124count, flawless-100% count, speed crown) are deliberately chosen to surface125stats the image itself doesn't show.126127## Companion design: "The Arena"128129A second visualization (speed × success × price, avatar markers sized130uniformly, price tag per model) was explored alongside the main leaderboard131and posted once as a one-off — its HTML/build script live only in session132scratchpads, not yet promoted into this directory. If asked to make it a133recurring post too, port `design-arena-v2.html`'s structure (GitHub avatar134thumbnails via `https://github.com/<user>.png?size=96`, pixelated via135nearest-neighbor resize, log-scaled x-axis, piecewise y-axis for the13695–100% success cluster, a simple pairwise-repulsion layout pass so137same-size markers don't overlap) following the same rendering/upload138pipeline as the main board.