Skip to content

Add degraded mode for older/weaker browsers - #3

Merged
vpetersson merged 2 commits into
masterfrom
degraded-mode-older-browsers
Jul 13, 2026
Merged

Add degraded mode for older/weaker browsers#3
vpetersson merged 2 commits into
masterfrom
degraded-mode-older-browsers

Conversation

@vpetersson

@vpetersson vpetersson commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Static Tailwind sibling to the birthday pilot (Screenly-Labs/birthday#1). Makes the app run on the support floor (Chrome 79 / Safari 11.1) and drop animation on weak hardware.

Build: esbuild (iife, es2017) replacing Bun.build + replaceChildren shim; Tailwind → @csstools/postcss-cascade-layers (flatten @layer) → Lightning CSS. 100vh fallback ahead of 100svh. Compiled CSS: 0 @layer.

Degraded gate: inline <head> script sets html.legacy on old/weak engines; CSS kill-switch drops animation/transition.

Verified both modes via headless screenshots (1920×1080 / 800×480): content renders in both, page fully styled. typecheck, lint, tests, es-check es2017 pass. Also gitignores .claude/.

🤖 Generated with Claude Code


Support floor updated: raised to Chrome 79 / Firefox 75 / Safari 11.1 / Edge 79 (from the initial ~2018/Chrome 65 target). The apps use clamp()/min()/max() pervasively, which require Chrome 79 (Safari 11.1); Lightning CSS cannot polyfill them, so Chrome 79 is the honest floor where the CSS renders. Still catches the vast majority of old signage players; WebKit stays at 2018 (Safari 11.1).

Static Tailwind sibling to the birthday pilot. On the ~2018 floor (Chrome 65 /
Safari 11.1) compiled Tailwind's @layer wrapping is dropped by engines below
Chrome 99 / Safari 15.4 (unstyling the page), and ?./?? is a parse-time error
that kills the JS bundle. This makes the full app run on the floor and drops
animation (weak hardware).

Build: esbuild (iife, es2017) replacing Bun.build + replaceChildren shim;
Tailwind -> @csstools/postcss-cascade-layers (flatten @layer) -> Lightning CSS
(lower/prefix/minify). 100vh fallback ahead of 100svh. One browserslist floor.

Runtime gate: inline <head> script flags html.legacy on old/weak engines; CSS
kill-switch drops animation/transition (content stays legible; entrances only
animate the reveal).

Also gitignores .claude/. Verified both modes via headless screenshots
(1920x1080 / 800x480): content renders in both, page fully styled. typecheck,
lint, tests, es-check es2017 all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a “degraded/legacy mode” path intended to keep the timer app working on an older (~2018) browser floor and to disable animations/transitions on weak devices, while also updating the build pipeline to emit older-compatible JS/CSS.

Changes:

  • Adds an inline legacy/weak-device gate in index.html that sets html.legacy, plus CSS rules that globally disable animations/transitions in that mode.
  • Updates the build to use Tailwind output + @csstools/postcss-cascade-layers + Lightning CSS for down-leveling/minification, and switches JS bundling from Bun.build to esbuild (iife, es2017).
  • Introduces a small replaceChildren polyfill module and imports it first in the browser entrypoint.

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
package.json Adds browserslist + new build toolchain devDependencies (postcss, cascade-layers, lightningcss, esbuild).
index.html Adds early legacy/weak-device detection and sets html.legacy before first paint.
bun.lock Locks new build-time dependencies.
build.js Switches CSS pipeline to Tailwind → flatten @layer → Lightning CSS; switches JS bundling to esbuild; uses browserslist for CSS targets.
assets/static/styles/tailwind.css Adds 100vh fallbacks and a legacy-mode animation/transition kill-switch.
assets/static/js/polyfills.ts Adds a replaceChildren shim for older engines.
assets/static/js/main.ts Imports polyfills first to ensure shims are installed before app code runs.
.gitignore Ignores .claude/ worktree/artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread build.js
Comment thread build.js Outdated
Comment thread index.html Outdated
Comment thread assets/static/js/polyfills.ts Outdated
…build

- browserslist floor -> chrome >= 79 / firefox >= 75 (keep safari 11.1, edge 79):
  the apps use clamp()/min()/max() pervasively, which need Chrome 79 (not 65).
- Degraded-mode gate: drop the CSS color-mix() probe (2023 -- it flagged capable
  2020-2022 browsers as legacy); detect old engines by the absent 2020-era
  Element.replaceChildren only; use classList.add('legacy') (idempotent).
- replaceChildren shim: build the new children in a DocumentFragment first so a
  bad node throws before the element is cleared (effectively atomic like native);
  reworded header (defensive shim; no hard-coded browser floor).
- build script: wrap the Lightning CSS step in try/catch with a per-file message;
  correct the comment that implied browserslist drives the JS floor (JS is a fixed
  esbuild es2017 floor kept in sync); refresh stale Bun.build references to esbuild.

Verified: typecheck/lint/tests + es-check es2017 pass; rebuilt with the new floor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 8 changed files in this pull request and generated 1 comment.

Comment thread package.json
@vpetersson
vpetersson merged commit 593187d into master Jul 13, 2026
2 checks passed
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.

2 participants