Skip to content

fix(public): load Google Fonts without render-blocking via same-origin fonts.js - #20

Merged
nish3451 merged 1 commit into
mainfrom
fix/render-blocking-fonts
Aug 8, 2026
Merged

nish3451 merged 1 commit into
mainfrom
fix/render-blocking-fonts

Conversation

@nish3451

@nish3451 nish3451 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What

The Google Fonts css2 stylesheet was fetched render-blocking on every public page — a <link rel="stylesheet"> in the homepage head and an @import chain inside shared.css for the shared pages (audit, agents, pricing, specimen, brief-requested). This change makes all six pages load the same css2 URL non-blocking through a same-origin, CSP-safe promotion path:

  • Each page preloads the css2 URL (rel="preload" as="style" data-fonts-css), loads the same-origin public/fonts.js promotion script (defer), and keeps a <noscript> stylesheet fallback so fonts still work without JavaScript.
  • shared.css no longer @imports the Google Fonts stylesheet.
  • src/worker.js registers /fonts.js in its PUBLIC_ASSET_PATHS allow-list (the worker 404s any unlisted asset-like path).
  • An inline onload swap is deliberately not used: the production CSP (script-src 'self', no unsafe-inline) blocks inline event handlers, so a same-origin served script is the promotion vehicle that works under the live CSP.

Guards and evidence

  • scripts/check-site.mjs gains static source guards: the blocking shape (font stylesheet link outside <noscript>, @import chain, missing preload/script/fallback, missing /fonts.js allow-list entry) fails npm run check on any of the six pages. These are source-string guards, not network-timing tests — CI has no browser.
  • scripts/test-agent-worker.mjs covers that the worker serves /fonts.js and 404s unlisted asset-like paths.
  • docs/evidence/render-blocking-fonts-2026-08-08.md records the local Chromium measurement (render-blocking status and first-paint vs css2 response under a simulated 1500ms CDN delay and the exact production CSP header, fonts still verified to load). The receipt states its own limits.

intended-outcome: six public pages (index, audit, agents, pricing, specimen, brief-requested) load the Google Fonts stylesheet without render-blocking, through a same-origin CSP-safe public/fonts.js promotion path, with a no-JS fallback retained.

verify: npm run check and npm test pass locally via test-gate; git diff --check clean; sgscan shows only baseline warnings; the browser receipt is local/static CSP-proxy evidence only — live deployment and live adoption remain unverified, and this PR does not claim the product is deployed or that live AI/search/performance improved.

Summary by CodeRabbit

  • Performance

    • Improved font loading across public pages to reduce render-blocking and support faster first paint.
    • Added graceful font-loading fallback when JavaScript is disabled.
  • Bug Fixes

    • Improved compatibility with the site’s content security policy while preserving custom fonts.
  • Tests

    • Added automated checks to verify font loading, asset serving, and non-blocking behavior.

…n fonts.js

The Google Fonts css2 stylesheet was fetched render-blocking on every
public page: a <link rel="stylesheet"> in the homepage head and an
@import chain inside shared.css for the shared pages (audit, agents,
pricing, specimen, brief-requested). All six pages now preload the same
css2 URL as a style resource, promote it through the same-origin
public/fonts.js script, and keep a <noscript> fallback; shared.css no
longer @imports the stylesheet, and src/worker.js registers /fonts.js in
its PUBLIC_ASSET_PATHS allow-list.

An inline onload swap is deliberately not used: the production CSP
(script-src 'self', no unsafe-inline) blocks inline event handlers, so
the promotion must come from a same-origin served script. scripts/check-
site.mjs gains static source guards asserting the blocking shape cannot
return on any of the six pages and that /fonts.js is served; the worker
and UI suites cover the allow-list and the promotion script contract.
docs/evidence/render-blocking-fonts-2026-08-08.md records the local
Chromium measurement (static copies, simulated CDN delay, production CSP
header) and explicitly states it is not CI proof and not a hosted/live
claim. No deployment or live before/after improvement is claimed.

Co-Authored-By: Claude <noreply@anthropic.com>

@greptile-apps greptile-apps Bot 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change replaces blocking Google Fonts imports with preloads and deferred same-origin stylesheet promotion across six public pages. It adds worker routing, static validation, worker tests, and measurement evidence for the new loading path.

Changes

Google Fonts loading

Layer / File(s) Summary
Page font loading markup
public/*.html, public/shared.css
Six pages now preload the Google Fonts stylesheet, defer fonts.js, and provide noscript fallbacks. The shared CSS import is removed.
Same-origin stylesheet promotion
public/fonts.js, src/worker.js
fonts.js promotes the marked preload to a stylesheet link. The worker allowlist serves the script at /fonts.js.
Loading validation and evidence
scripts/check-site.mjs, scripts/test-agent-worker.mjs, docs/evidence/...
Checks and tests validate markup, asset routing, promotion behavior, fallback handling, and recorded timing evidence.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant fonts.js
  participant GoogleFonts
  Browser->>GoogleFonts: Preconnect and preload stylesheet
  Browser->>fonts.js: Load deferred same-origin script
  fonts.js->>Browser: Append stylesheet link from preload URL
  Browser->>GoogleFonts: Reuse preloaded stylesheet
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: preventing Google Fonts from blocking rendering through a same-origin fonts.js loader.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/render-blocking-fonts

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
scripts/check-site.mjs (2)

437-443: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert that the promotion script reuses the preload URL.

The guard checks the selector, stylesheet relation, and append operation. It does not check link.href = preload.href. A script that loads another URL, or no URL, would pass the check.

Suggested guard
-  if (!fontScript.includes('link.rel = "stylesheet"') || !fontScript.includes('document.head.appendChild(link)')) {
+  if (
+    !fontScript.includes("link.href = preload.href") ||
+    !fontScript.includes('link.rel = "stylesheet"') ||
+    !fontScript.includes("document.head.appendChild(link)")
+  ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-site.mjs` around lines 437 - 443, Extend the fontScript
validation in the existing promotion-script checks to require assignment of the
preload URL via link.href = preload.href. Keep the current selector, stylesheet
relation, and document.head.appendChild(link) assertions unchanged, and add a
failure message for scripts that do not reuse preload.href.

454-458: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the inline-handler guard independent of attribute order.

The regular expression only matches data-fonts-css before onload. A tag with onload before data-fonts-css bypasses the check.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-site.mjs` around lines 454 - 458, Update the inline-handler
validation in the page HTML check so it detects both data-fonts-css and onload
attributes regardless of their order within the same link tag. Preserve the
existing failure message and page validation behavior.
docs/evidence/render-blocking-fonts-2026-08-08.md (1)

97-99: 🚀 Performance & Scalability | 🔵 Trivial

Add a post-deployment browser smoke check.

The receipt explicitly limits proof to local static copies and source checks. Before treating the change as verified in production, check the deployed six pages for a successful /fonts.js response, the production CSP, and non-blocking css2 loading.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/evidence/render-blocking-fonts-2026-08-08.md` around lines 97 - 99,
Extend the verification documented in the Limitation section with a
post-deployment browser smoke check covering all six deployed pages. Validate
successful /fonts.js responses, the production CSP, and non-blocking css2
loading before claiming production verification, while retaining the existing
distinction between local evidence and live deployment evidence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/evidence/render-blocking-fonts-2026-08-08.md`:
- Line 53: Update the reproduction script’s result object to include a
fontsReady field populated from document.fonts.status, so the reported
font-readiness claim is directly reproducible; otherwise remove the fontsReady
claim from the evidence document.

---

Nitpick comments:
In `@docs/evidence/render-blocking-fonts-2026-08-08.md`:
- Around line 97-99: Extend the verification documented in the Limitation
section with a post-deployment browser smoke check covering all six deployed
pages. Validate successful /fonts.js responses, the production CSP, and
non-blocking css2 loading before claiming production verification, while
retaining the existing distinction between local evidence and live deployment
evidence.

In `@scripts/check-site.mjs`:
- Around line 437-443: Extend the fontScript validation in the existing
promotion-script checks to require assignment of the preload URL via link.href =
preload.href. Keep the current selector, stylesheet relation, and
document.head.appendChild(link) assertions unchanged, and add a failure message
for scripts that do not reuse preload.href.
- Around line 454-458: Update the inline-handler validation in the page HTML
check so it detects both data-fonts-css and onload attributes regardless of
their order within the same link tag. Preserve the existing failure message and
page validation behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ab2a132c-622f-403f-a4ee-c213f147fe30

📥 Commits

Reviewing files that changed from the base of the PR and between 6172ef9 and 89bb083.

📒 Files selected for processing (12)
  • docs/evidence/render-blocking-fonts-2026-08-08.md
  • public/agents.html
  • public/audit.html
  • public/brief-requested.html
  • public/fonts.js
  • public/index.html
  • public/pricing.html
  • public/shared.css
  • public/specimen.html
  • scripts/check-site.mjs
  • scripts/test-agent-worker.mjs
  • src/worker.js
💤 Files with no reviewable changes (1)
  • public/shared.css


### Fonts still load, stylesheet still applies

Both states, all six pages: `fontsReady: "loaded"`, `karla: true`, `fraunces: true`, `sheetApplied: true` in the fixed state. First paint uses the fallback stack and swaps in via the existing `display=swap` in the URL. No CSP violations in the fixed state (the single console error on `brief-requested.html` is the pre-existing `gtag/js?id=AW-XXXXXXXXX` placeholder, present in both states).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make the font-readiness claim reproducible.

The receipt reports fontsReady: "loaded", but the reproduction script does not return a fontsReady field. Add fontsReady: document.fonts.status to the result or remove that claim.

Suggested fix
   return { fcp, css2End, renderBlockingStatus: rbs,
+    fontsReady: document.fonts.status,
     waitedForCss2: fcp !== null && css2End !== null ? fcp >= css2End : null,

Also applies to: 85-89

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/evidence/render-blocking-fonts-2026-08-08.md` at line 53, Update the
reproduction script’s result object to include a fontsReady field populated from
document.fonts.status, so the reported font-readiness claim is directly
reproducible; otherwise remove the fontsReady claim from the evidence document.

@nish3451
nish3451 merged commit c5599bc into main Aug 8, 2026
3 checks passed
@nish3451
nish3451 deleted the fix/render-blocking-fonts branch August 8, 2026 18:47
nish3451 added a commit that referenced this pull request Aug 8, 2026
…6e942a (#24)

The render-blocking receipt documented a limitation: the live deployment was
never measured. This closes that gap by recording a real-Chromium measurement
of the six deployed tinystudio.io pages (2026-08-09): the Google Fonts css2
stylesheet is non-blocking everywhere, first paint does not wait for it, the
only render-blocking resources are the site's own same-origin stylesheets, and
fonts still load and apply. Dogfood finding b8f6046e942a (render-blocking
resources on home) is verified resolved on the deployed site; the code fix and
CI enforcement were merged as PRs #20 and #23.
nish3451 added a commit that referenced this pull request Aug 8, 2026
…6e942a (#25)

The render-blocking receipt documented a limitation: the live deployment was
never measured. This closes that gap by recording a real-Chromium measurement
of the six deployed tinystudio.io pages (2026-08-09): the Google Fonts css2
stylesheet is non-blocking everywhere, first paint does not wait for it, the
only render-blocking resources are the site's own same-origin stylesheets, and
fonts still load and apply. Dogfood finding b8f6046e942a (render-blocking
resources on home) is verified resolved on the deployed site; the code fix and
CI enforcement were merged as PRs #20 and #23.
nish3451 added a commit that referenced this pull request Aug 9, 2026
…t current main and live (#35)

The code-side fix (PR #20) and CI enforcement (PR #23) for dogfood finding
b8f6046e942a ("Render-blocking resources on home") are already merged in
origin/main. This lane re-verified the guarantee still holds after the
subsequent page edits (heading hierarchy, apple-touch icon, schema.org, meta
descriptions, canonical URLs, internal-link cleanup, App Store citation):

- npm run check:render-blocking passes on all six pages (real Chromium,
  production CSP, css2 delayed 2500ms): css2 non-blocking, first paint never
  waits for it, no render-blocking resources other than the site's own
  same-origin stylesheets.
- Fresh live measurement of the deployed pages confirms the same: css2
  non-blocking on all six pages, only same-origin stylesheets render-block,
  fonts still load and apply under the production CSP.

Nothing further to change; the receipt now records the closeout on the current
head so the finding cannot be re-opened by tracker drift.
nish3451 added a commit that referenced this pull request Aug 10, 2026
…t current main and live (#69)

The code-side fix (PR #20) and CI enforcement (PR #23) for dogfood finding
b8f6046e942a ("Render-blocking resources on home") are merged in origin/main;
this lane re-verified the guarantee on the current head (536b3c9, 2026-08-10)
after the commits that landed since the 2026-08-09 closeout (sitemap,
preferred source pages, Agent Desk de-index, tap targets, CI runners):

- npm run check:render-blocking passes on all six pages (real Chromium,
  production CSP, css2 delayed 2500ms): css2 non-blocking, first paint never
  waits for it, no render-blocking resources other than the site's own
  same-origin stylesheets, promoted sheet applied.
- Fresh live measurement of the deployed pages confirms the same: css2
  non-blocking on all six pages, only same-origin stylesheets render-block,
  fonts still load and apply under the production CSP.
- Full npm test (82 tests) passes on this head.

The receipt now records the re-verification on the current head so the
tracker item can close.
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