2026-09-18 · 27 min · webgpu · small-models · on-device-inference · browser-ml · edge-ai · model-architecture
Six projects, six task-specific neural networks, six browser tabs, zero servers. All six ship as static assets small enough to sit next to a favicon, and every one of them runs inference on WebGPU (or, for a single short query, plain CPU JavaScript — more on that twist below) rather than calling an API. The seed was Vercel Labs engineer Shu Ding's gpu-lexer: a 41,321-parameter, 27.64 KiB (28,305 bytes, Brotli-compressed) syntax highlighter that guesses a source file's language instead of being told it. Within days, the same trick landed on four more problems — natural-language dates, natural-language search filters, natural-language cron schedules, and Arabic word morphology — plus one deliberately silly one: centering a div. This piece characterizes all six completely, because at these sizes that is actually possible, then builds the economic and architectural case for why this is a real, narrow, recurring shape of problem and not just a viral weekend format.
The cluster, characterized completely
| Project | Author | Params | Shipped size | Task | Headline metric |
|---|---|---|---|---|---|
| gpu-lexer | Shu Ding (Vercel Labs) | 41,321 | 28,305 B (27.64 KiB) | syntax highlighting, no language ID | 83.02% Shiki agreement (held-out) |
| gpu-time | Arik Chakma | 38,745 | 45,561 B (44.5 KiB, full pkg) | English text → dates / RFC 5545 | 97.6% exact match, real English |
| gpu-query | safzanpirani | 29,597 | 40,960 B (40 KiB, weights) | search phrase → structured filter | 98.88% transfer accuracy (unseen schemas) |
| neural-flexbox | Aaron Vanston | 36,354 | 33,801 B (33.0 KiB) | approximate one CSS flex row | 94.03% of coords within 1px |
| gpu-cron | @ManuSchiller (no repo found) | 35,783 | ~35,494 B (bundle, measured) | English text → cron expression | not published — see below |
| tinySarf | Ahmed Abdel-Aal | 245,063 | 239,894 B (234.3 KiB, full pkg) | Arabic morphological analysis | 87.02% teacher-label agreement (not human gold) |
Every number in that table is either read directly from a committed
MODEL_CARD.md/README, or — for gpu-cron — printed live in the demo's own
footer (35,783 parameters · WebGPU · 6-bit weights). None of it is
estimated. That is unusual for anything claiming to be a machine-learning
result, and it is the direct consequence of the size: you cannot hide much
inside 30-word footers and 82-line training scripts.
The seed: gpu-lexer's 27.64 KiB
gpu-lexer's whole public surface is one function:
import { parse } from "gpu-lexer"
const spans = await parse("const answer = 42")
// [{ type: "keyword", start: 0, end: 5 }, ...]No language argument, no bundled grammar. A CPU pass splits source into words, whitespace, newlines, and individual symbols and packs cheap features per part — kind, a logarithmic length bucket, edge characters, hashes, neighboring-symbol shape. A tiny WebGPU model (32 hidden channels: a summed feature embedding, a five-part local window, an exact bidirectional affine scan run as a parallel prefix — a Blelloch-style scan, the operation a GPU is actually built for — then a shared-weight binary tree merging blocks bottom-up and propagating context back down) assigns each part one of nine visual classes: plain, comment, string, number, keyword, type, function, constant, operator. Adjacent equal labels merge into the spans you get back.
The promoted checkpoint is trained against Shiki's own labels — so "accuracy" here means agreement with a specific existing highlighter, not some independent ground truth about programming-language semantics — and reaches 83.02% per-part agreement, 77.73% styled macro F1, on a corpus held disjoint from training at the repository and package level. (An earlier, higher-sounding 88.02% figure circulated publicly before a taxonomy relabeling; the model card is explicit that the two numbers use different label sets and are not comparable — a small, honest correction sitting in the repo for anyone who reads past the README.) The whole training loop warm-starts from the last promoted checkpoint and requires a strict overall-accuracy improvement over that checkpoint to auto-promote; a run that regresses a "protected" language beyond a statistical tolerance gets flagged even when the aggregate score improves.

That per-language table is the single most useful thing on the page, because
it is a ceiling admitted in public: held-out agreement runs 95–100% for
Angular/JSX-family languages, sits in the 80s–90s for most general-purpose
languages, and drops below 50% for jinja, liquid, razor, vala,
and vb — templating and less-common languages that likely appear rarely in
training. "Language-agnostic" here means one shared architecture and
classifier, not equal accuracy on every language you might paste in; the
model guesses structure from local shape, and shape that is unfamiliar
enough gets it wrong.
Against comparison libraries the size story is not close: 27.6 KiB versus Prism.js's 162.1 KiB (all 297 languages) or 8.6 KiB (six major web languages), Highlight.js's 240.4 KiB, Shiki's 991.5 KiB, Starry Night's 1.46 MiB. On the same "top-25 GitHub-language, popularity-weighted" agreement metric, gpu-lexer's own site reports 86.77% against Shiki's 100% reference, ahead of Prism.js (84.05%), Sugar High (73.61%), Starry Night (72.25%), and Highlight.js (70.12%) — one model, one bundle, covering every language at once, rather than a grammar pack per language.
The joke that is also a real artifact: neural-flexbox
Aaron Vanston's neural-flexbox states its own thesis on the homepage: "Stop using a 10-trillion-parameter model to centre your divs. Use a 36,354-parameter model instead." The author is explicit that this is "considerably less useful" than gpu-lexer — CSS flexbox is a deterministic layout algorithm the browser already computes exactly, for free, so learning an approximation of it has no practical upside. The point is what training one costs.
The model is a plain MLP — 23 → 128 → 128 → 128 → 2, ReLU activations, per-output-channel int8 quantized hidden layers — trained on 152,000 layouts actually measured in Chromium 149: 1 to 8 boxes in a single flex row, integer basis/grow/shrink, six justify modes. Predict x-position and width, in pixels, from 23 numeric features. That is the entire task.
Here is the training script's model definition and training loop, in full — this is not an excerpt, this is the whole thing that produces the shipped checkpoint, aside from argument parsing:
# packages/training/src/experiment.py — neural-flexbox
x, y, w = dataset('train'); vx, vy, vw = dataset('validation')
modules = []; last = x.shape[1]
for _ in range(a.depth):
modules.extend([nn.Linear(last, a.width), nn.ReLU()]); last = a.width
modules.append(nn.Linear(last, 2)); model = nn.Sequential(*modules).to(a.device)
# ... optional weight-resume/expansion here ...
optimizer = torch.optim.AdamW(model.parameters(), lr=a.lr, weight_decay=0)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, a.epochs, eta_min=a.lr * .01)
best = float('inf')
for epoch in range(a.epochs):
for ids in torch.randperm(len(x), device=a.device).split(a.batch):
pred = model(x[ids])
errors = nn.functional.smooth_l1_loss(pred * w[ids, None], y[ids] * w[ids, None], beta=a.beta, reduction='none')
loss = errors.mean()
optimizer.zero_grad(); loss.backward(); optimizer.step()
scheduler.step()
with torch.no_grad():
score = ((model(vx) - vy).abs() * vw[:, None]).mean().item()
if score < best:
best = score; best_state = copy.deepcopy(model.state_dict())
model.load_state_dict(best_state)The whole file, packages/training/src/experiment.py, is 82 lines
including the argparse setup and the JSON export at the end. The recipe that
produced the shipped refined-v1 checkpoint chains five of these runs —
seed float, expanded float, balanced float, canonical float, then two
quantization-aware passes — and the final stage's own recorded
report.json states trainingSeconds: 177.53 on a CUDA GPU for the
800-epoch run that produced the deployed weights: under three minutes. Not
three minutes per stage across a multi-day pipeline — 177.5 seconds is the
wall-clock time of the specific run whose weights are what ships today.
The result: 0.35px mean coordinate error, p95 1.08px, on 5,000 held-out generated layouts in the same 240–1,200px training-width range. The model card is equally direct about where that breaks: an explicit out-of-distribution split (1,000 layouts at 1,300–1,800px container widths, outside the training range) scores 0.946px mean error, 3.51px p95, 76.67px maximum, and the fraction of predicted coordinates within 1px of the true answer falls from 94.4% in-distribution to 74.4% out of it. Nothing crashes; the model just gets quietly, measurably worse the moment the input leaves the box it was trained inside — which is exactly the failure mode every one of these six projects has to answer for, in its own way, below.

Two ports of one idea: gpu-time and gpu-query
gpu-time (Arik Chakma) turns English time expressions into dates, time
ranges, and RFC 5545 recurrence rules — "Sat Sun 1pm-8pm Mon 10pm-12am" with a
reference instant and timezone becomes real ISO occurrences plus an RRULE
string. Its model card lists 38,745 parameters, two bidirectional scan
layers, 580 embedding rows, and 35 role labels decoded with a 40×40 CRF
transition matrix (Viterbi), so the model scores whole label sequences
rather than committing to each token independently. Weights pack to 22,501
Brotli bytes; the complete published package is 45,561 Brotli bytes, "under
the 50,000-byte release limit" the project holds itself to. On a
never-shown-to-training slice of a public sentence corpus it gets 5,866 of
6,011 real English sentences exactly right (97.6%).
It is also candid about exactly how it fails, in a limitations section that
reads like a bug tracker rather than marketing copy: "in four minutes"
(elapsed time) gets read as a future clock time; a friend literally named
Wednesday reads as the weekday; 07/19/27 misreads its trailing two digits
as a day rather than a year; the em dash is unsupported entirely (13:20—15:50
returns nothing, while an en dash works on a weaker feature path). The
homepage's own explainer video, separately, still cites an older
24,761-parameter figure for the model — a small, visible reminder that
when five people ship variations on one idea inside a week, even a project's
own marketing can lag its own model card by a checkpoint or two.
gpu-query (safzanpirani) turns a typed search phrase into a structured
filter against your schema, without ever learning your field names — a
29,597-parameter model that reads "anything record listens and performer
containing uncensored please" against a schema of album/artist/genre
fields (aliased as record/performer/style) and compiles it to
[{ field: "album", cmp: "eq", value: "listens" }, { field: "artist", cmp: "contains", value: "uncensored" }]. Its own README does not hedge about
where the architecture came from:
The architecture is a port of gpu-time's
TimeTagger. Only the lexicon, the label set, the generator and the CPU resolver are new.
The model — 32 hidden channels, the same sum-embed → five-token convolution → bidirectional gated affine scan → two-layer head shape as gpu-time — reads your schema as three extra rows of structural features per token ("this token matched a field of this kind," "this token is one position from a field") with the literal field names dropped at the boundary, so renaming a column changes the parse's resolution but not what the model itself sees. On schemas drawn from four domains that share no field name, alias, or enum value with training, it hits 98.88% exact-filter-match accuracy, up from 98.65% once the training run removed a hashed word-identity feature — evidence, the README argues, that the model was reading structure and the word hashes were mostly noise.
# spike/model.py — gpu-query's QueryTagger, architecture excerpt
HIDDEN = 32
def affine_scan(gate, candidate):
"""Inclusive scan for state[t] = gate[t] * state[t-1] + candidate[t]."""
width = gate.shape[1]; stride = 1
while stride < width:
next_gate = gate[:, stride:] * gate[:, :-stride]
next_candidate = candidate[:, stride:] + gate[:, stride:] * candidate[:, :-stride]
gate = torch.cat((gate[:, :stride], next_gate), dim=1)
candidate = torch.cat((candidate[:, :stride], next_candidate), dim=1)
stride *= 2
return candidateThat affine_scan — a textbook parallel-prefix (Blelloch) scan, log(n)
sequential steps instead of n — is the specific reason this architecture
maps onto a GPU at all: the recurrence that carries context across a
sequence is associative, so it decomposes into independent per-channel scans
that a WGSL compute kernel can run one workgroup per query, one thread per
hidden channel. Both backends — plain TypeScript and the WGSL kernel — read
the same 40 KiB of int6 weights and are checked against each other and
against the PyTorch reference to within 1e-3. A short single query stays on
the CPU by design, because dispatch and readback cost more than the parse
itself; WebGPU only pays for itself in batch:
| Batch | CPU | WebGPU | Speedup |
|---|---|---|---|
| 32 | 7.0 ms | 2.6 ms | 2.7× |
| 256 | 40.6 ms | 3.7 ms | 11.0× |
| 1,024 | 208.5 ms | 15.4 ms | 13.5× |
| 4,096 | 1,084.6 ms | 67.1 ms | 16.2× |
(Measured on an Apple M4, 1,024 queries per row above scaled to the stated batch size.) The whole feasibility spike — never published to npm, by its own description — trains in under two minutes on an M-series Mac for 40 epochs over 60,000 generated samples per epoch; the README notes plainly that "these models do not need a GPU; Python data generation dominates the loop," which is a genuinely different economic statement than anything about a frontier model's training run.


Testing the two I could push the hardest: gpu-cron and tinySarf
gpu-cron and tinySarf are the two projects in this cluster with the least public accountability — gpu-cron because there is no repository at all to read, tinySarf because it explicitly ships without an independent human-gold evaluation. So instead of reading a model card, I drove both live demos headlessly with Playwright (Chromium, WebGPU enabled) and typed at them.
gpu-cron converts English scheduling phrases into cron expressions. Loaded
cold, "Every weekday at 9:30am" resolves via WebGPU in 130ms into 30 9 * * 1-5, with a correct human-readable readout and five real upcoming
occurrences in the selected timezone. The footer states its own numbers
plainly: 35,783 parameters · WebGPU · 6-bit weights, and the three-stage
pipeline it advertises — "recognize" (the model), "resolve" (calendar
arithmetic), "be exact" (a compiler that refuses to guess) — is the same
shape every other project in this piece uses.

Then I tried to break it. Feeding it a phrase whose grammar it recognizes but whose composition plain cron cannot express — "The last Friday of every month at 5pm" — the model tags every single token correctly, at a self-reported 100.0% model score ("last" as a prefix, "Friday" tagged as an excluded weekday, "every"/"month" as recurrence, "5"/"pm" as hour/meridiem) — and the compiler still refuses, with a specific, legible diagnostic: "A monthly ordinal combined with a weekday requires an unsupported nth-weekday rule." Same story for "Every 90 minutes" — perfectly tagged, rejected because a plain five-field cron minute slot cannot express a 90-minute interval. Both are correct behavior: the model did its job; the five-field cron format itself is the ceiling. That is a meaningfully different failure than the model being wrong, and the UI is honest about the distinction — model confidence and compiler success are two separate, visible numbers, not one blended "success" indicator.
The one that is not fine: I typed asdkfjasdf random gibberish text — no
schedule content whatsoever. The model tagged it as a real, structured
recurrence at 95.8% model score: asdkfjasdf as a weekday, random as
an excluded weekday, gibberish as a weekday, text as a recurrence marker,
predicted family "biweekly." It confidently hallucinated grammatical
structure onto noise. The compiler still rejected the output — but only
because cron happens to require a numeric field this particular gibberish
never produced ("The model did not identify a required numeric value"), not
because anything detected that the input was nonsense. Feed it four garbage
words that happen to include a number, and nothing in this pipeline would
catch it. The model's own confidence score is not a reliable
out-of-distribution detector; the only thing standing between this input and
a fabricated cron job was a downstream syntax requirement it happened to
violate.

tinySarf (Ahmed Abdel-Aal) analyzes Modern Standard Arabic word morphology — segmenting a word into morphemes, recovering its triliteral root, and tagging part of speech and grammatical features. Its own homepage is unusually forthcoming about its status: "Experimental, unpromoted. Full-analysis and POS quality remain below release targets; independent human gold is absent." The model — 245,063 reachable int8 weights, a 220K-parameter multi-task CNN for segmentation and grammar plus a separate 25K-parameter root CNN — is trained on just 5,470 words / 75,135 teacher-generated analyses, entirely on a CPU (an Apple M2, per the model card's own recorded environment; this one never touches a GPU during training at all), and evaluated against labels generated by CAMELMORPH, an existing rule-based Arabic morphological analyzer — not against independent human annotation.
Segmentation exact match lands at 87.02% and root exact match at 78.24% against that teacher. But the number that matters most for what this tool is actually good for is buried two rows down: full-analysis top-1 accuracy is 12.52% (17.18% at top-3). Individual fields — root, POS, each grammatical feature — mostly look solid in isolation; getting every one of them right simultaneously, which is what "analyze this word correctly" actually requires, is a much harder bar, and errors across eight-plus output slots compound fast. This is the clearest example in the whole cluster of why a single headline accuracy number can flatter a system that is genuinely useful for some of its outputs and not yet reliable for the compound task.
I fed it a real inflected word first — وبكتابهم ("and with their book") —
and it correctly segmented all four morphemes (و conjunction, ب preposition,
كتاب stem, هم pronominal enclitic), recovered the root كتب, and tagged it
correctly as a masculine singular genitive-construct noun, in 285ms on the
CPU reference backend. Then I gave it a modern loanword with no Arabic
triliteral root at all: كومبيوتر ("computer"). It correctly declined to
force a fake root — Root and Pattern both come back explicitly "Unknown,"
and the whole word is tagged as a single unanalyzable stem, in 19.8ms. That
is the right behavior for exactly the reason gpu-cron's gibberish case was
the wrong one: the model recognized the limits of what it could honestly
claim, rather than manufacturing structure to fill the answer shape.


The size, on one axis
This is not one benchmark — the browser models solve six different narrow problems and the general models solve one broad one, so the Y axis is two honestly-different series, not a shared leaderboard. What the log X axis shows plainly is scale: 29,597 to 245,063 parameters for all six browser models versus 1.24 billion to 405 billion for five ordinary open-weight language models — five to seven orders of magnitude, and the closed frontier is further right still, at a size nobody discloses.
None of these six numbers is directly comparable to another benchmark — a syntax highlighter and an Arabic morphology analyzer are not competing on the same task, so the Y axis above is two honestly-labeled series, not one leaderboard. What the shared, logarithmic X axis earns is the only claim this piece actually needs: 29,597 to 245,063 parameters, 27.6 KiB to 234 KiB shipped, for every model in this cluster, against 1.24 billion to 405 billion parameters for five ordinary open-weight instruction models running the same well-known MMLU benchmark. That is five to seven orders of magnitude on parameters, and the size gap is even more dramatic measured in bytes actually sent to a client: an estimated 2.3 to 755 GiB of bf16 weights for the general models, against literally hundreds of kilobytes, total, for all six of these combined.
The economics
Assumptions, stated plainly: the API side is Claude Haiku 4.5’s published $1 / $5 per million input/output tokens, costing a typical 50-in/30-out parse-this-phrase call $0.0002 every single time. The browser side is gpu-lexer’s real, measured bundle size — 27.6 KiB — at an assumed $0.10/GB CDN egress rate, paid once when a visitor’s browser downloads it and never again for that visitor. It is not a crossover chart: the browser model is already cheaper at call one, and every call after that widens the gap, because one side scales with calls and the other does not scale with calls at all.
The chart above is not a crossover chart, on purpose — there is no point where the lines meet, because the two costs are not the same shape of cost. An API call to Claude Haiku 4.5 (Anthropic's cheapest current model, published at $1 / $5 per million input/output tokens) costs something on every single request: a typical 50-token-in, 30-token-out "parse this phrase" call is $0.0002, and that number is exactly as true on call one as on call one million. A CDN-delivered browser model costs a fraction of a cent to ship — gpu-lexer's real 28,305 bytes, at a representative $0.10/GB CDN egress rate, is about $0.0000028 — and that cost is paid once per visitor, not once per call. Every inference after the page loads runs on that visitor's own GPU, for exactly $0, with no server in the loop at all. At the very first call the browser model is already roughly 76 times cheaper; by a few hundred calls in one session it is tens of thousands of times cheaper, and the ratio keeps climbing because one side scales with usage and the other structurally does not.
That gap is the whole economic argument, but it is not the only one. Every demo in this piece reported its own inference latency, unprompted, because these teams treat milliseconds as a headline number: 2.40ms for neural-flexbox, 19.8ms for tinySarf's WebGPU path (285.4ms on its CPU reference), 130ms for gpu-cron's first WebGPU call, single-digit-to-low-double-digit milliseconds for gpu-query and gpu-time at realistic batch sizes. A round trip to an API endpoint — network, queue, generation, network again — rarely clears that bar even under good conditions, and never clears it when the network itself is the bottleneck (a flaky connection, a background tab, a country with a slow route to the nearest datacenter). None of these six models has a rate limit, a per-minute quota, a cold-start queue, or a privacy surface where the input phrase leaves the device — because none of them send the input anywhere.
What shape of task this actually fits
Every one of these six problems shares four properties, and the shape is worth naming because it recurs constantly in ordinary software and rarely gets this treatment: narrow (one well-defined transformation, not general reasoning), high-volume (called on every keystroke, every paste, every page load — gpu-query explicitly targets a live search bar), latency- sensitive (a syntax highlighter or a search-as-you-type parser that takes 200ms feels broken even if it is "fast" by API standards), and — the property that makes a tiny model sufficient rather than merely cheap — a constrained output space. gpu-lexer emits one of nine span classes. gpu-time and gpu-cron emit roles from a closed set (35, in gpu-time's case) decoded into a fixed calendar/cron grammar. gpu-query emits one of twelve token roles compiled into a small filter algebra. tinySarf emits morpheme spans, a root, and features from closed inventories, one already-known per Arabic morphology.
That is exactly the same shape of problem this site covers from the decoding side in Parallel constrained decoding: when the space of valid outputs is small and known ahead of time, you do not need a model that can produce any token sequence and then constrain it after the fact — you can build the constraint into the architecture (or the decoding process) itself and spend orders of magnitude less compute getting there. This cluster and that one are two attacks on the same underlying observation from opposite ends: parallel constrained decoding keeps a big general model but restricts what it is allowed to say; these six projects throw the big model away entirely and train something the size of a favicon that could never say anything else in the first place. Both routes exist because most decisions software actually needs to make — is this a keyword, what date is "next Tuesday," which field does "genre" alias — do not need a frontier model's generality. They need a fast, cheap, correct answer to one small question, over and over.
Where it breaks
None of this is a case for replacing general models with tiny ones broadly — it is a case for recognizing which slice of problems never needed the big model at all, and the honest edges of that slice showed up in every single project tested here:
- Out-of-distribution input degrades quietly, not loudly. gpu-lexer's
own agreement table drops below 50% on
jinja,liquid,razor,vala, andvb— real, common-enough languages, just underrepresented in training. neural-flexbox's explicit out-of-distribution split shows mean error nearly tripling and the fraction of coordinates within 1px falling from 94.4% to 74.4% the moment container widths move outside the 240–1,200px training range. Nothing throws an error in either case; the answer is simply worse, silently. - A confident model is not the same as a correct out-of-distribution detector. gpu-cron tagged four gibberish words as a 95.8%-confident biweekly schedule. The self-reported score told me nothing useful about whether the input made sense; only a downstream syntax constraint (cron needs a number somewhere) happened to catch it this time.
- Some ceilings belong to the output format, not the model. gpu-cron parsed "the last Friday of every month" and "every 90 minutes" perfectly and still failed, because five-field cron cannot express either schedule. That is worth distinguishing from a model mistake, and the project's own UI does distinguish it — model score and compiler success are shown as two separate numbers.
- A compound task's exact-match rate can crater even when every field looks fine alone. tinySarf's segmentation (87.02%) and root (78.24%) numbers look production-ready in isolation; full-analysis top-1 accuracy — every field correct at once — is 12.52%. Eight-plus output slots compound errors fast.
- The evaluation itself can be the weak link. tinySarf's numbers are agreement with an existing rule-based analyzer's labels, not independent human-reviewed ground truth, and the project says so, prominently, on its own homepage. gpu-time's real-English figure (97.6%) is a genuinely held-out test; gpu-query's transfer figure (98.88%) is measured on schemas disjoint from training. Reading which claim rests on which kind of evidence is most of the actual diligence here.
- Even WebGPU is not the default path. gpu-query, gpu-time, and tinySarf all keep a single short query on the CPU by design, because dispatch and readback latency exceeds the parse time itself at that scale — WebGPU only earns its keep once inputs batch up. tinySarf's own browser benchmark measured WebGPU running slower than a plain JavaScript reference (0.89×) for a single word, and only ahead (2.34×) at a batch of 128. The "tab" in "browser-tab model" is doing real work, but for most of these, most of the time, that work is happening on the CPU.
One weekend, five forks
The lineage here is explicit and self-reported, not inferred: neural-flexbox's
README credits gpu-lexer by name as its direct inspiration; gpu-query's
README states its architecture "is a port of gpu-time's TimeTagger," with
gpu-lexer and gpu-time both named under "prior art." The five public
repositories' most recent commits — 16 September (gpu-lexer and gpu-time), 12
September (gpu-query), 11 September (neural-flexbox), 14 September (tinySarf)
— sit inside a single week, with gpu-cron's live demo (no repo, no commit
history to check) part of the same cluster by every account describing it.
One person's small, well-documented idea — small model, one narrow task, real
model card, real benchmark page — turned into a template that four or five
other people could pick up, port, and ship inside days, because the hardest
part (proving a WebGPU-inference pipeline this small actually works in a
real browser) had already been done once, in public, with the training code
attached. That the fifth fork was a joke about centering a div, and that the
joke came with a real 82-line training script and an honest
out-of-distribution evaluation split, is the most telling detail in the
whole cluster: the format had gotten cheap and legible enough, in one week,
that even the parody was rigorous.
Sources: gpu-lexer · gpu-time · gpu-query · neural-flexbox · tinySarf · gpu-cron demo at gpu-cron.vercel.app (no public repository found). Model cards and architecture docs read directly from each repository; gpu-cron's figures and failure cases are from live testing, 18 September 2026. MMLU figures for the general-model comparison are each model's own published card (Llama 3.2 1B/3B, Llama 3 8B, Llama 3.1 405B — Meta; Phi-3-mini — Microsoft). Claude Haiku 4.5 pricing is Anthropic's published API rate.