Skip to report
Chief / Bettter feedback widget 1.2.0 (OperationalLayer · lab · ops)13 Nov 2026, 00:10 UTC

Taking the screenshot can no longer block feedback

The feedback widget's screenshot now has Cancel, Escape and an 8-second limit, and pages that froze or lost their screenshot get one in under 4 seconds; live on the lab, ops follows its merge.

Lab: live and checked · Ops: waiting for its merge

Seconds until the feedback card opens, widget 1.2.0 (labels: what 1.1.0 did on the same page)

Some pictures hang (1.1.0: never ended)0.53 s
Another site's pictures, some hang (1.1.0: never ended)3.3 s
120 mixed cards, scrolled (1.1.0: no screenshot)0.88 s
A picture answers with a web page (1.1.0: no screenshot)0.32 s
2,000 cards, scrolled down (1.1.0: 8.1 s, 4.3 s frozen)1.3 s
Pictures still loading on the page (1.1.0: 4.3 s)3.4 s
Browser never finishes drawing: the 8 s limit, sent without one8 s
Source: demo.html with demo_server.py, local Chrome via browser-use, 12 Nov 23:5x UTC; 1.1.0 and 1.2.0 on the same pages

What people see

Before (1.1.0)

  • "Taking a screenshot…" can stay forever (Vlada, 12 Nov)
  • No Cancel; Escape does nothing
  • The page's sticky header stays shifted while it waits
  • One bad picture: the item goes without a screenshot

Now (1.2.0)

  • Cancel or Escape at any moment: write without a screenshot
  • After 8 s the card opens anyway; everything else is sent
  • The page is always put back as it was
  • A picture that does not arrive is grey; "Try again" keeps the text

Before: still taking a screenshot after 30 seconds

Demo page dimmed behind a 'Taking a screenshot…' box with no button, 30 seconds after the click, widget 1.1.0
Widget 1.1.0 on demo.html (40 design cards; the screenshot's copies of some pictures never answer), 30 s after the click. Local Chrome, 12 Nov.

Now: Cancel and Esc are on the veil

Demo page dimmed behind a 'Taking a screenshot…' box with a Cancel button and the line 'Esc or Cancel: write it without a screenshot'
Widget 1.2.0, same page, 1 s after the click (decoding forced to hang to keep the veil up). Cancel opened the card 0.4 s after the click.

Live on the lab: the card with its screenshot

The feedback card on the Mayer brand page of tech-builder.bettter.us with 'Attach the screenshot' ticked and a thumbnail
https://tech-builder.bettter.us/mayer/ scrolled down (56 pictures, 11,424 px long): screenshot in 2.5 s on a busy machine. The check item it sent (tb-0104) was deleted at 00:07:57 UTC.

Without a screenshot: the reason, and Try again

The feedback card saying 'No screenshot: you skipped it. The page and what you pointed at are still sent. Try again', with the comment kept
After Esc: the card says why, and Try again keeps the kind and the comment (checked in local Chrome).

The 2,000-card page scrolled to 20,000 px (seconds)

1.1.0 until the card opens (quiet)8.1 s
1.1.0 longest freeze (quiet)4.3 s
1.2.0 until the card opens (quiet)1.3 s
1.2.0 longest freeze (quiet)0.8 s
1.1.0 until the card opens (busy, slower run)12.7 s
1.2.0 until the card opens (busy, slower run)2 s
Source: demo.html?grid=2000&kinds=ok, local Chrome; quiet machine 12 Nov 23:5x UTC; busy machine (load 7-13) 13 Nov 00:02 UTC, two runs each

The screenshot still matches the page

Side by side: the 2,000-card demo page as Chrome draws it, and the widget's screenshot of it, with the same cards in the same places
Left: the page. Right: 1.2.0's screenshot. Boxes entirely off-screen are copied without their contents; on a stress page (collapsing margins, floats, escaping elements) the screenshots were pixel-identical to 1.1.0's.

Where it is

  1. Widget 1.2.0

    OperationalLayer PR #45: the fix, tests, demo, contract field

  2. Lab merged

    Lab PRs #35 and #36 merged into the lab's main

  3. Lab live

    Deployed 13 Nov 00:06 UTC from main a9497db; checked in a real browser

  4. Ops: after merge

    PR #45 waits for the merge session; ops refreshes within 10 min of it

Not done yet
  • ops.bettter.us still runs widget 1.1.0: OperationalLayer PR #45 is open for the merge session (this repo's rule); ops picks it up within 10 minutes of the merge and was not checked live with 1.2.0.
  • The platform (Upcycle-Studio) has its own copy of the widget; its session (9f1ff34421) is fixing it with the same behaviour, not released yet.
  • On the lab, a browser that loaded the page in the last hours may keep 1.1.0 for up to about 1.5 h (the lab sends no cache header for the widget file); ops sends no-cache.
Why it froze
  • The screenshot is drawn from the page itself by html-to-image. It fetched every picture again, full size, off-screen ones too, with no time limit: one picture that never answered kept "Taking a screenshot…" up for good, and its open requests used up the site's six connections.
  • One picture that was not a picture (an error page, a broken file) cost the whole screenshot.
  • On long pages it copied every element with about 470 styles each, in one go: the page froze for seconds.
  • Nothing could stop it: no Cancel, no Escape, no limit; the sticky header stayed shifted until it ended.
  • The 1×1 grey placeholder both widgets carried was itself a broken PNG (found by the platform session).
What the widget does now
  • An 8-second limit (screenshotTimeout), Cancel and Escape; the page is put back however it ends; picture requests stop with it.
  • Pictures the page shows are drawn from the page at the size shown; another site's are fetched with 3 s each (at most 12 MB, six at a time) and shrunk; off-screen ones are never fetched; anything that fails is grey.
  • Boxes entirely off-screen are copied without their contents (same size, nothing moves).
  • Each item says what happened to its screenshot (context.screenshot: attached, left out, timeout, cancelled or failed, the time, pictures missing); the inbox shows it. Additive v1 contract field.
Checks run
  • node --test shared/feedback-widget/test/capture.test.js: 9 passed (time limit, Cancel, failure, picture paths, 12 MB cap, valid placeholder, cut-off copy). Breaking the restore, the timer or the abort makes them fail.
  • python3 -m unittest discover -s opsdash/tests: 65 passed; docs/contracts/check.py: 0 problems.
  • Lab: 18-23 widget tests passed; the full lab suite fails the same 3 tests and 2 errors on main with and without the change (missing local data and pins).
  • Browser (local Chrome, browser-use): eight demo pages before and after; timeout, Cancel, Escape, Send and Try again; a stress page compared with 1.1.0 pixel by pixel.
  • Lab rebuild compared with the live site before deploying: of 1,567 files only the build stamp, the build time and the two widget files differed.
New feedback from people (checked 13 Nov 00:07 UTC)
  • Ops inbox: none.
  • Adapter: Elena Hordiienko left 32 items on 12 Nov (23 blazers on v1.6.21, 9 trousers), still new; the Adapter session (1505d1af9f) was told.
  • Platform: one new question (12 Nov 13:11 UTC) about the test preselection spreadsheet.
  • Lab: Catarina's notes tb-0073 to tb-0103 are being integrated by the lab session (416b42ca30).