Skip to content

perf: run the scene in a worker, paint the hero on the first frame, polish SEO and UX - #17

Merged
benatespina merged 2 commits into
mainfrom
claude/web-optimization-ui-ux-perf-cff8ed
Oct 30, 2026
Merged

benatespina merged 2 commits into
mainfrom
claude/web-optimization-ui-ux-perf-cff8ed

Conversation

@benatespina

@benatespina benatespina commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Summary

Lighthouse 100 on mobile and desktop, with accessibility and SEO at 100.

  • three.js moves to a Web Worker on an OffscreenCanvas. scene.ts touches no DOM; it talks to wherever it runs through a SceneHost. scene-worker.ts renders, scene-client.ts picks the path (worker, or the page for browsers without OffscreenCanvas WebGL) and pins the callouts from what the scene reports. The main thread keeps only the scroll spring and a handful of style writes.
  • The hero is painted on the first frame. It settles into place with a transform-only animation and never fades or waits for a script (a compositor fade keeps Chrome from counting the text as LCP at all). The intro is now the scene's loading state: the ruler draws itself to the head while the readout counts up, then the scene takes its place.
  • SEO: JSON-LD (SoftwareSourceCode, Organization, WebSite), og:locale, sitemap link and lastmod, noindex on the 404 page, public/_headers with immutable caching for /_astro/* and safety headers.
  • UX / a11y: nav landmark, finger-sized link targets, larger mode toggle, 2px focus ring, live region on the copy button, a heading for the facts section, CLS-free intro.
  • No more prefetch script (every link leaves the site); the mono font is preloaded too.

Lighthouse (pnpm build && pnpm preview, Lighthouse 13)

Mobile before Mobile after Desktop before Desktop after
Performance 41 100 92 100
LCP 7.3 s 0.9 s 0.2 s 0.2 s
TBT 7,460 ms 0 ms 230 ms 0 ms
CLS 0.014 0 0.014 0.001
Accessibility / SEO 100 / 100 100 / 100 100 / 100 100 / 100

Best practices reads 96 locally only because the Cloudflare beacon cannot load offline.

Verification

  • pnpm check and pnpm build pass.
  • Checked in a browser: worker path and page fallback (with OffscreenCanvas removed), light and dark modes, the intro on a first visit at desktop and phone widths, the whole story (callouts, readout, rebuild counter) and the closing section.

benatespina and others added 2 commits October 30, 2026 23:12
Lighthouse on mobile scored 41: the hero was held at opacity 0 until the
intro finished, and three.js loaded, compiled and rendered on the main
thread, which the intro waited on. LCP 7.3 s, TBT 7.5 s.

The scene now runs in a Web Worker on an OffscreenCanvas wherever the
browser allows it. scene.ts touches no DOM any more: everything it needs
from the page comes through a SceneHost, so the same module runs in the
worker (scene-worker.ts) or on the page for browsers without OffscreenCanvas
WebGL (older Safari). scene-client.ts picks the path, sends the beat with one
frame in flight at a time, and pins the callouts on the page from what the
scene reports. The main thread is left with the scroll spring and a few style
writes: TBT is 0 ms on both presets.

The hero no longer waits for anything. It is painted, legible, on the first
frame and settles into place with a transform-only animation; a fade would
keep Chrome from counting the text as the LCP at all. The intro (the ruler
drawing itself up to the head, the readout counting from 000 001) becomes
the scene's loading state, drawn in the stage beside the copy, and gives way
to the scene when it is ready. Its elements are placed by transforms, so the
intro no longer shifts layout.

Also: no prefetch script (every link leaves the site), the third font
preloaded (the install command is in the hero), the story's CSS height
matched to the timeline, and the scene skipped entirely while it is covered.

Mobile 41 → 100 (LCP 0.9 s, TBT 0 ms, CLS 0); desktop 92 → 100.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Search engines get JSON-LD for the framework (SoftwareSourceCode), the
organisation and the site, an og:locale, a link to the sitemap with a lastmod,
and a noindex on the 404 page. public/_headers gives the hashed build output a
year of immutable cache and sets the usual safety headers.

On the page: a nav landmark, link targets padded to a finger's size without
moving the type, a slightly larger mode toggle, a 2px focus ring, a live region
that announces the copied install command, and a heading for the facts section
so the outline no longer jumps from h1 to h3.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@benatespina
benatespina merged commit cc7c872 into main Oct 30, 2026
1 of 2 checks passed
@benatespina
benatespina deleted the claude/web-optimization-ui-ux-perf-cff8ed branch October 30, 2026 22:13
benatespina added a commit that referenced this pull request Oct 31, 2026
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