Skip to content

feat(pixel-peeper), feat(garage): the share card and a pretext panel draw real HTML into canvas - #1649

Merged
oddharsh merged 1 commit into
mainfrom
claude/html-canvas-leverage-0955a8
Nov 10, 2026
Merged

oddharsh merged 1 commit into
mainfrom
claude/html-canvas-leverage-0955a8

Conversation

@oddharsh

Copy link
Copy Markdown
Owner

Chrome 157 turned on HTML-in-Canvas (ctx.drawElementImage) by default on 2026-11-03. This puts it in the two places on the site where it earns its bytes.

/pixel-peeper: the share card is HTML

drawCard hand-painted the 1200x630 card: about 70 lines of fillRect, gradient stops and 16 fillText calls at fixed positions, in hex copied from luna.css. cardHTML now writes it with the page's own tokens and classes, and it reuses shareGridHTML and shareKeyHTML, so the card and the page can't drift. cardCanvas paints it in a hidden holder and copies it into the canvas that Copy image, Save PNG and Preview already used.

drawCard stays as the fallback: for Safari, Firefox and Chrome before 157, and for any draw that throws or reads back a blank title bar. Its needle labels and footer line now share needleLabels and cardFoot with the HTML card.

What the holder has to be, measured in Chrome 157 on 2026-11-10:

holder result
1px clipping box at the viewport origin whole card drawn, also on a 390px phone and below the fold
opacity:0 / clip-path drawn
visibility:hidden, display:none, zero size throws "No cached paint record"
off-screen (left:-10000px, left:200vw, a translate) throws on this page; drew transparent without throwing on a bare test page
the CSS-shrunk preview canvas itself clips the drawable child

So the card draws in the 1px holder, and the finished canvas moves into the preview.

/garage/pretext: the other way into a canvas

Section 3 gets a second panel. It shows the same paragraph wrapped around a real CSS float, drawn into a canvas on each paint event and driven by the same slider. It breaks line for line with the layoutNextLine panel at 1280 and 390px. The copy says what the trade costs: a layout pass per tick, in exchange for all of CSS. Browsers without the API hide the panel and say why.

Checked

  • Chrome 157.0.8103.51 and Canary 159.0.8154.0 (headless, against bun run dev): wireShare produces the Save PNG blob, Preview shows the drawn canvas, and the holder cleans itself up.
  • Chrome 152 (browser pane): the card falls back to drawCard, and pretext hides its panel and shows the note. No console errors.
  • Control: forcing the holder off-screen makes cardCanvas reject, and the card falls back.
  • check:fast green. The first run had 1 failing test that I couldn't reproduce in two reruns, so I don't know which one it was. pages:check and derive:check are clean.
  • bun run build against origin/main 100efe6: no /a/ asset re-mints. Brotli q11: /pixel-peeper +967 B, /garage/pretext +589 B.

Known limit: Safari and Firefox users get the old card until they ship the API, so both card paths live in the page for now. Deleting drawCard becomes possible once they do.

…draw real HTML into canvas

Chrome 157 turned on HTML-in-Canvas (ctx.drawElementImage) by default on
2026-11-03. One canvas on the site was rebuilding what HTML already does,
and one explainer was missing the other half of its argument.

/pixel-peeper's share card was about 70 lines of fillRect, gradient stops
and 16 fillText calls at hardcoded positions, in hex copied from luna.css.
It's now HTML on the page's own tokens and classes, and it reuses the share
grid and key the page shows above it. A hidden holder paints it, and
drawElementImage copies it into the 1200x630 canvas that Copy image, Save
PNG and Preview already used. drawCard stays as the fallback for Safari,
Firefox and Chrome before 157, and for any draw that throws or reads back
blank.

Measured in Chrome 157 on 2026-11-10: a 1px clipping box at the viewport
origin paints the whole card, even on a 390px phone and below the fold.
visibility:hidden, display:none, a zero-size box and every off-screen
position tried throw "No cached paint record". A canvas shrunk by CSS
clips its drawable child, so the card draws in the holder and the finished
canvas moves into the preview.

/garage/pretext section 3 gets a second panel: the same paragraph wrapped
around a real CSS float, drawn into a canvas on each paint event, driven
by the same slider. It breaks line for line with pretext's layoutNextLine
panel at 1280 and 390px. Browsers without the API hide the panel and say
why.

Brotli at q11: /pixel-peeper +967 B, /garage/pretext +589 B. No /a/ asset
re-mints against origin/main 100efe6.
@github-actions

Copy link
Copy Markdown
Contributor

Wire-size diff vs merge base

7fdfd6cfb38ab63b3f82ab9a30c0c4a516b58b34 → 32e46a161b668591a20dc59ada3dd0ef36a5f89b

Brotli q11, the quality the edge serves. Every number here is deterministic:
an unchanged file produces no row. Advisory — this check fails on nothing.

Client assets

No change. 40 files, 245.02 KiB Brotli total.

Pages

Total Brotli: 718.80 KiB → 720.32 KiB (+1.52 KiB, +0.2%) across 77 files, 2 changed.

file base head Δ
pixel-peeper/index.html 24.25 KiB 25.19 KiB +0.94 KiB (+3.9%)
garage/pretext.html 8.87 KiB 9.45 KiB +0.58 KiB (+6.5%)

Worker bundle

299.34 KiB → 299.38 KiB gzip (+0.04 KiB, +0.0%)

Largest module deltas (raw bytes in bundle):

file base head Δ
.build/src/worker/lib/csp-hashes.ts 5.57 KiB 5.62 KiB +0.05 KiB (+0.8%)

Dictionary transport

Family dictionary acquisition: no change, 14.50 KiB q11.

pd/: 446 → 448 deltas, 525.78 KiB → 538.80 KiB (+13.02 KiB).

Head tags vs merge base

No change. 77 documents, every title, description, canonical, robots, og:*, twitter:*, alternate, JSON-LD type and oracle status identical.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
aadhar-sh b043712 Commit Preview URL

Branch Preview URL
Nov 10 2026, 07:46 PM

@oddharsh
oddharsh merged commit a651606 into main Nov 10, 2026
10 checks passed
@oddharsh
oddharsh deleted the claude/html-canvas-leverage-0955a8 branch November 10, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant