#455 by GitHub stars

GoogleChrome/modern-web-guidance

Keep your coding agent up to date with the latest web best practices

History

Review weekly changes to SKILL.md before updating. Dates mark the weeks in which we observed each version; checks apply to the recorded commits.

View weekly changes

skills/chrome-extensions/SKILL.md

Week of Oct 26, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

4f2b13e25c58 → 4f2b13e25c58

Compare on GitHub

skills/modern-web-guidance/SKILL.md

Week of Oct 26, 2026 · +0 / −0 lines

Before Network or broad shell → After Network or broad shell

4f2b13e25c58 → 4f2b13e25c58

Compare on GitHub

View on GitHubAdd to my skills

Verified commit 4f2b13e25c5815b3f080ca0d983e828d96561a0f

git clone --filter=blob:none --no-checkout https://github.com/GoogleChrome/modern-web-guidance.git .hotskills/googlechrome-modern-web-guidance && git -C .hotskills/googlechrome-modern-web-guidance checkout --detach 4f2b13e25c5815b3f080ca0d983e828d96561a0f # Copy each selected skill directory from .hotskills/googlechrome-modern-web-guidance into .claude/skills/<skill-name>/
git clone --filter=blob:none --no-checkout https://github.com/GoogleChrome/modern-web-guidance.git .hotskills/googlechrome-modern-web-guidance && git -C .hotskills/googlechrome-modern-web-guidance checkout --detach 4f2b13e25c5815b3f080ca0d983e828d96561a0f # Copy each selected skill directory from .hotskills/googlechrome-modern-web-guidance into .gemini/skills/<skill-name>/
2.6kGitHub stars
41stars in 7 days
2skills in this repository
5commits in 30 days

Heat

6.3
  • Star growth, last 7 daysAhead of 90% of tracked repositories
  • Star growth, last 24 hoursAhead of 71% of tracked repositories
  • Rank movement, last 7 daysAhead of 40% of tracked repositories
  • Commits, last 30 daysAhead of 70% of tracked repositories
  • Accounts asking about it through MCP, last 7 daysNot available
  • Hot votes this weekAhead of 0% of tracked repositories

Heat never changes the order by stars, and sponsorship never touches it. How heat works

Stars over time

Aug 2, 2026Nov 6, 20262,631

Individual skills in this repository

How it works

chrome-extensions

When your agent uses it

Build and publish Chrome Extensions using Manifest V3 best practices. Use this skill whenever the user asks to create, modify, debug, or understand Chrome browser extensions, add-ons, or anything involving the Chrome Extensions API. Trigger on mentions of: 'Chrome extension', 'browser extension', 'manifest.json', 'content script', 'service worker' (in browser context), 'popup' (in browser extension context), 'side panel', 'chrome.* API', 'declarativeNetRequest', 'omnibox', 'context menu' (in extension context), 'userScripts', 'user script', 'script manager', or any request to build functionality that integrates with the Chrome browser UI. Also trigger for publishing to the Chrome Web Store: 'publish extension', preparing an extension for publishing, responding to a review rejection, writing permission justifications, or drafting a privacy policy.

What it loads into context

Frontmatter

199 tokens

Always available to the agent

SKILL.md

6,078 tokens

When the skill is activated

Reference documents

22,916 tokens

Loaded on request

Token counts are estimates. Scripts run separately; they are not counted as reference context.

The playbook

  1. Part 1 — Building Extensions
  2. Part 2 — Publishing to the Chrome Web Store
  3. Reference Files
  4. Output Checklist

Files

  • ../../.claude-plugin/marketplace.jsonasset360 bytes
  • ../../.claude-plugin/plugin.jsonasset196 bytes
  • SKILL.mdcore26,456 bytes
  • SKILL.mdcore26,456 bytes
  • references/extensions/api-calling.mddoc2,188 bytes
  • references/extensions/auth-identity.mddoc4,036 bytes
  • references/extensions/content-scripts.mddoc3,506 bytes
  • references/extensions/context-menus.mddoc1,844 bytes
  • references/extensions/csp-sandbox.mddoc4,810 bytes
  • references/extensions/declarative-net-request.mddoc2,794 bytes
  • references/extensions/devtools.mddoc2,889 bytes
  • references/extensions/icons.mddoc2,756 bytes
  • references/extensions/media-capture.mddoc4,805 bytes
  • references/extensions/message-passing.mddoc4,214 bytes
  • references/extensions/omnibox.mddoc1,819 bytes
  • references/extensions/permissions.mddoc4,641 bytes
  • references/extensions/popup-ui.mddoc2,378 bytes
  • references/extensions/prompt-api.mddoc3,835 bytes
  • references/extensions/service-worker.mddoc4,591 bytes
  • references/extensions/side-panel.mddoc4,480 bytes
  • references/extensions/storage.mddoc1,965 bytes
  • references/extensions/tab-management.mddoc3,756 bytes
  • references/extensions/user-scripts.mddoc9,414 bytes
  • references/webstore/chromewebstore-template.mddoc5,786 bytes
  • references/webstore/privacy-policy.mddoc4,247 bytes
  • references/webstore/review-checklist.mddoc7,074 bytes
  • references/webstore/store-listing.mddoc8,033 bytes
Read SKILL.md

# Chrome Extensions

Build production-quality Chrome extensions using Manifest V3 and publish them to the Chrome Web Store.

## Part 1 — Building Extensions

### Mandatory Rules

These address the most common causes of broken extensions. Violating any produces a non-functional build.

#### 1. Icons: only reference files you create — or omit icons entirely

```
❌ BROKEN — referencing files that don't exist or reusing one file for all sizes:
View the complete source on GitHub

Skills included

  • chrome-extensions
  • modern-web-guidance

Repository facts

License
Apache-2.0
Created
Mar 23, 2026
Last pushed
Nov 6, 2026
Forks
102
Open issues
0
Project activity
Active

Rank over the last 12 weeks

Now #455 · best #384 · down 56 in 30 days

  1. #448 on Nov 1
  2. #450 on Nov 2
  3. #451 on Nov 3
  4. #452 on Nov 4
  5. #453 on Nov 5
  6. #455 since Nov 6
80 earlier periods
  1. #399 on Aug 2
  2. #405 on Aug 7
  3. #408 on Aug 8
  4. #405 on Aug 9
  5. #423 on Aug 10
  6. #419 on Aug 11
  7. #411 on Aug 12
  8. #419 on Aug 13
  9. #418 on Aug 14
  10. #413 on Aug 15
  11. #417 on Aug 16
  12. #415 on Aug 17
  13. #418 on Aug 18
  14. #420 on Aug 19
  15. #414 on Aug 20
  16. #417 on Aug 21
  17. #406 on Aug 22
  18. #418 from Aug 23 to Aug 24
  19. #422 on Aug 25
  20. #419 on Aug 26
  21. #424 from Aug 27 to Aug 28
  22. #417 on Aug 29
  23. #409 on Aug 30
  24. #423 on Aug 31
  25. #426 on Sep 1
  26. #420 on Sep 2
  27. #422 on Sep 3
  28. #410 on Sep 4
  29. #407 on Sep 5
  30. #390 on Sep 6
  31. #398 on Sep 7
  32. #400 on Sep 8
  33. #398 on Sep 9
  34. #399 on Sep 10
  35. #398 from Sep 11 to Sep 12
  36. #397 on Sep 13
  37. #404 on Sep 14
  38. #405 on Sep 15
  39. #406 on Sep 16
  40. #398 on Sep 17
  41. #400 on Sep 18
  42. #392 on Sep 19
  43. #400 on Sep 20
  44. #396 on Sep 21
  45. #402 on Sep 22
  46. #394 on Sep 23
  47. #392 on Sep 24
  48. #389 on Sep 25
  49. #384 on Sep 26
  50. #392 on Sep 27
  51. #395 on Sep 28
  52. #408 on Sep 29
  53. #401 on Sep 30
  54. #399 on Oct 1
  55. #401 on Oct 2
  56. #389 on Oct 3
  57. #387 on Oct 4
  58. #394 from Oct 5 to Oct 6
  59. #402 on Oct 7
  60. #399 on Oct 8
  61. #410 on Oct 9
  62. #400 on Oct 10
  63. #402 on Oct 11
  64. #411 on Oct 12
  65. #407 on Oct 13
  66. #412 on Oct 14
  67. #413 on Oct 15
  68. #418 on Oct 16
  69. #409 on Oct 17
  70. #417 on Oct 18
  71. #419 on Oct 19
  72. #421 on Oct 20
  73. #425 on Oct 21
  74. #424 on Oct 22
  75. #423 on Oct 23
  76. #417 on Oct 24
  77. #437 on Oct 25
  78. #443 on Oct 28
  79. #444 on Oct 29
  80. #447 from Oct 30 to Oct 31

Before you install

Network or broad shell

Automated signals, not a guarantee

Checked Nov 2, 2026

Changed on Oct 27, 2026

No longer found: Possible obfuscation, Access to secrets

Not fully analyzed: some files were too long, unreadable or missing. This never lowers the level.

Show 3 notes
  • skills/chrome-extensions/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • skills/modern-web-guidance/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
  • skills/modern-web-guidance/SKILL.md:1 Analysis incomplete: Referenced executable target unavailable; not analyzed
Show all 485 signals by file

skills/chrome-extensions/SKILL.md

  • Dangerous shell operationline 58
    Extension CSP blocks `eval()`, `new Function()`, inline `<script>` in all extension pages.
  • Dangerous shell operationline 65
    eval(userCode); // CSP blocks this
  • Dangerous shell operationline 71
    window.addEventListener('message', (e) => { eval(e.data.js); /* allowed in sandbox */ });
  • Dangerous shell operationline 505
    - [ ] Code execution uses sandbox/blob/srcdoc — no `eval()` in extension pages

skills/chrome-extensions/references/extensions/api-calling.md

  • Network accessline 10
    curl -H "Origin: https://example.com" -I https://api.openweathermap.org/data/2.5/weather?q=London&appid=KEY`
  • Network accessline 13
    If the response includes either `*` or `https://example.com` as the value for the `Access-Control-Allow-Origin` header, the API supports CORS.
  • Network accessline 18
    {   "host_permissions": [     "https://no-cors-api.example.com/*"
  • Network accessline 19
    "host_permissions": [     "https://no-cors-api.example.com/*"   ]
  • Network accessline 20
    "https://no-cors-api.example.com/*"
  • Network accessline 32
    // From popup or service worker const response = await fetch('https://api.openweathermap.org/data/2.5/weather?q=London&appid=KEY');
  • Network accessline 33
    const response = await fetch('https://api.openweathermap.org/data/2.5/weather?q=London&appid=KEY');
  • Network accessline 42
    async function callAPI(url) {   try {     const response = await fetch(url);
  • Network accessline 43
    try {     const response = await fetch(url);     if (!response.ok) {
  • Network accessline 44
    const response = await fetch(url);
  • Access to secretsline 66
    [Credential-related source omitted]

skills/chrome-extensions/references/extensions/auth-identity.md

  • Network accessline 9
    "client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",     "scopes": [       "https://www.googleapis.com/auth/userinfo.profile",
  • Network accessline 10
    "scopes": [       "https://www.googleapis.com/auth/userinfo.profile",       "https://www.googleapis.com/auth/userinfo.email"
  • Network accessline 11
    "https://www.googleapis.com/auth/userinfo.profile",
  • Network accessline 12
    "https://www.googleapis.com/auth/userinfo.email"
  • Network accessline 42
    async function getUserProfile(token) {   const response = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
  • Network accessline 43
    const response = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
  • Network accessline 59
    [Credential-related source omitted]
  • Network accessline 60
    [Credential-related source omitted]
  • Network accessline 131
    const authUrl = `https://github.com/login/oauth/authorize?client_id=XXX&redirect_uri=${redirectUrl}`;

skills/chrome-extensions/references/extensions/csp-sandbox.md

  • Dangerous shell operationline 9
    - `eval()`, `new Function()`, `setTimeout("string")`
  • Dangerous shell operationline 39
    approaches. **Extension CSP completely blocks `eval()`, `new Function()`, and inline scripts in
  • Dangerous shell operationline 45
    `eval()` and inline scripts, but they cannot access chrome.* APIs.
  • Dangerous shell operationline 101
    eval(js);
  • Dangerous shell operationline 166
    eval(userCode); // CSP blocks this

skills/chrome-extensions/references/extensions/icons.md

  • Network accessline 69
    for SIZE in 16 48 128; do   cat > "icons/icon-${SIZE}.svg" << EOF <svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">
  • Network accessline 70
    cat > "icons/icon-${SIZE}.svg" << EOF <svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">   <rect width="${SIZE}" height="${SIZE}" rx="$((SIZE/4))" fill="#4688F1"/>
  • Network accessline 71
    <svg xmlns="http://www.w3.org/2000/svg" width="${SIZE}" height="${SIZE}" viewBox="0 0 ${SIZE} ${SIZE}">

skills/chrome-extensions/references/extensions/omnibox.md

  • Network accessline 19
    try {     const response = await fetch(
  • Network accessline 20
    const response = await fetch(
  • Network accessline 21
    `https://en.wikipedia.org/w/api.php?action=opensearch&search=${encodeURIComponent(text)}&limit=5&format=json`
  • Network accessline 40
    chrome.omnibox.onInputEntered.addListener((text, disposition) => {   const url = text.startsWith('http') ? text     : `https://en.wikipedia.org/wiki/${encodeURIComponent(text)}`;
  • Network accessline 42
    : `https://en.wikipedia.org/wiki/${encodeURIComponent(text)}`;
  • Network accessline 80
    {   "host_permissions": ["https://en.wikipedia.org/*"]
  • Network accessline 81
    "host_permissions": ["https://en.wikipedia.org/*"]

skills/chrome-extensions/references/extensions/permissions.md

  • Network accessline 8
    {   "permissions": ["tabs", "scripting", "storage"],   "host_permissions": ["https://api.example.com/*"]
  • Network accessline 9
    "permissions": ["tabs", "scripting", "storage"],   "host_permissions": ["https://api.example.com/*"] }
  • Network accessline 10
    "host_permissions": ["https://api.example.com/*"]

skills/chrome-extensions/references/extensions/tab-management.md

  • Network accessline 30
    // Create const tab = await chrome.tabs.create({ url: 'https://example.com', active: true });
  • Network accessline 31
    const tab = await chrome.tabs.create({ url: 'https://example.com', active: true });
  • Network accessline 33
    // Update await chrome.tabs.update(tabId, { url: 'https://new-url.com', pinned: true });
  • Network accessline 34
    await chrome.tabs.update(tabId, { url: 'https://new-url.com', pinned: true });
  • Network accessline 124
    // Create a new window with specific tabs const win = await chrome.windows.create({ url: 'https://example.com', focused: true });
  • Network accessline 125
    const win = await chrome.windows.create({ url: 'https://example.com', focused: true });

skills/chrome-extensions/references/extensions/user-scripts.md

  • Network accessline 18
    "minimum_chrome_version": "120",   "permissions": ["userScripts"],   "host_permissions": ["https://example.com/*"]
  • Network accessline 19
    "permissions": ["userScripts"],   "host_permissions": ["https://example.com/*"] }
  • Network accessline 20
    "host_permissions": ["https://example.com/*"]
  • Network accessline 79
    await chrome.userScripts.register([{   id: 'my-script',   matches: ['https://example.com/*'],
  • Network accessline 80
    id: 'my-script',   matches: ['https://example.com/*'],   js: [{ code: 'alert(1)', file: 'user-script.js' }] // Error: specify code OR file, not both
  • Network accessline 81
    matches: ['https://example.com/*'],
  • Network accessline 90
    await chrome.userScripts.register([{   id: 'my-user-script',   matches: ['https://example.com/*'],
  • Network accessline 91
    id: 'my-user-script',   matches: ['https://example.com/*'],   js: [{ file: 'user-script.js' }],
  • Network accessline 92
    matches: ['https://example.com/*'],
  • Network accessline 98
    await chrome.userScripts.register([{   id: 'my-user-script',   matches: ['https://example.com/*'],
  • Network accessline 99
    id: 'my-user-script',   matches: ['https://example.com/*'],   js: [{ code: userProvidedCode }]
  • Network accessline 100
    matches: ['https://example.com/*'],
  • Network accessline 113
    await chrome.userScripts.register([{     id: 'my-user-script',     matches: ['https://example.com/*'],
  • Network accessline 114
    id: 'my-user-script',     matches: ['https://example.com/*'],     js: [{ code: userProvidedCode }]
  • Network accessline 115
    matches: ['https://example.com/*'],

skills/chrome-extensions/references/webstore/privacy-policy.md

  • Network accessline 124
    - **Missing data types**: If your extension uses `chrome.storage.sync`, that data goes to   Google's servers — disclose this. If you make any `fetch()` calls, disclose what's sent.
  • Network accessline 125
    Google's servers — disclose this. If you make any `fetch()` calls, disclose what's sent.

skills/chrome-extensions/references/webstore/review-checklist.md

  • Dangerous shell operationline 113
    rm -f "$OUTPUT"
  • Access to secretsline 116
    [Credential-related source omitted]
  • Access to secretsline 119
    [Credential-related source omitted]

skills/chrome-extensions/references/webstore/store-listing.md

  • Network accessline 178
    **Fix:** - Audit every `fetch()`, `XMLHttpRequest`, and `chrome.storage.sync` call
  • Network accessline 179
    - Audit every `fetch()`, `XMLHttpRequest`, and `chrome.storage.sync` call

skills/modern-web-guidance/guides/accessibility/accessible-error-announcement.md

  • Network accessline 11
    See [MDN aria-invalid](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-invalid) for more details.

skills/modern-web-guidance/guides/built-in-ai/language-detection.md

  • Network accessline 65
    <iframe     src="https://cross-origin.example.com/"
  • Network accessline 66
    src="https://cross-origin.example.com/"

skills/modern-web-guidance/guides/built-in-ai/language-model.md

  • Network accessline 166
    - **Aborting Tasks**: Use `AbortController` to allow users to stop long-running generations. Pass the `signal` to `prompt()` or `promptStreaming()`, not to `LanguageModel.create()`. - **Security**: Use Permission Policies to control access 
  • Network accessline 168
    - **Design**: Review the [People + AI Guidebook](https://pair.withgoogle.com/guidebook/) to ensure responsible AI implementation.
  • Network accessline 174
    For the full detailed list of dos and don'ts, see https://developer.chrome.com/docs/ai/built-in-ai-dos-donts.md.txt. Below is the gist:
  • Network accessline 203
    For the Prompt API, each session [tracks the context of the conversation](https://developer.chrome.com/docs/ai/prompt-api?content_ref=each+session+keeps+track+of+the+context+of+the+conversation+previous+interactions+are+taken+into+account+f
  • Network accessline 204
    conversation](https://developer.chrome.com/docs/ai/prompt-api?content_ref=each+session+keeps+track+of+the+context+of+the+conversation+previous+interactions+are+taken+into+account+for+future+interactions+until+the+session+s+context+window+is
  • Network accessline 224
    **Do:** Explicitly call [`destroy()`](https://developer.chrome.com/docs/ai/prompt-api#terminate_a_session) on
  • Network accessline 240
    output, not just chunks, because malicious code could be split across updates. Before rendering, use the [Sanitizer API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where
  • Network accessline 241
    Before rendering, use the [Sanitizer API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where supported. To avoid a decrease in performance, use a streaming Markdown parser
  • Network accessline 242
    API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where
  • Network accessline 244
    like [streaming-markdown](https://github.com/thetarnav/streaming-markdown).
  • Network accessline 266
    **Do:** When you need the model to return data in a specific format, use [structured output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+
  • Network accessline 267
    [structured output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+s+response+by+passing+a+json+schema+to+the+languagemodel+prompt+and+langu
  • Network accessline 268
    output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+s+response+by+passing+a+json+schema+to+the+languagemodel+prompt+and+languagemodel+pro
  • Network accessline 278
    *Applies to: Prompt API, as it's the only API that supports [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api).*
  • Network accessline 279
    schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api).*
  • Network accessline 284
    **Don't:** Enforce strict character limits like `maxLength: 125` using [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api). When a
  • Network accessline 285
    [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api). When a

skills/modern-web-guidance/guides/built-in-ai/prompt-api.md

  • Network accessline 166
    - **Aborting Tasks**: Use `AbortController` to allow users to stop long-running generations. Pass the `signal` to `prompt()` or `promptStreaming()`, not to `LanguageModel.create()`. - **Security**: Use Permission Policies to control access 
  • Network accessline 168
    - **Design**: Review the [People + AI Guidebook](https://pair.withgoogle.com/guidebook/) to ensure responsible AI implementation.
  • Network accessline 174
    For the full detailed list of dos and don'ts, see https://developer.chrome.com/docs/ai/built-in-ai-dos-donts.md.txt. Below is the gist:
  • Network accessline 203
    For the Prompt API, each session [tracks the context of the conversation](https://developer.chrome.com/docs/ai/prompt-api?content_ref=each+session+keeps+track+of+the+context+of+the+conversation+previous+interactions+are+taken+into+account+f
  • Network accessline 204
    conversation](https://developer.chrome.com/docs/ai/prompt-api?content_ref=each+session+keeps+track+of+the+context+of+the+conversation+previous+interactions+are+taken+into+account+for+future+interactions+until+the+session+s+context+window+is
  • Network accessline 224
    **Do:** Explicitly call [`destroy()`](https://developer.chrome.com/docs/ai/prompt-api#terminate_a_session) on
  • Network accessline 240
    output, not just chunks, because malicious code could be split across updates. Before rendering, use the [Sanitizer API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where
  • Network accessline 241
    Before rendering, use the [Sanitizer API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where supported. To avoid a decrease in performance, use a streaming Markdown parser
  • Network accessline 242
    API](https://developer.mozilla.org/docs/Web/API/HTML_Sanitizer_API) where
  • Network accessline 244
    like [streaming-markdown](https://github.com/thetarnav/streaming-markdown).
  • Network accessline 266
    **Do:** When you need the model to return data in a specific format, use [structured output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+
  • Network accessline 267
    [structured output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+s+response+by+passing+a+json+schema+to+the+languagemodel+prompt+and+langu
  • Network accessline 268
    output](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api?content_ref=he+prompt+api+lets+you+specify+a+json+output+format+of+the+model+s+response+by+passing+a+json+schema+to+the+languagemodel+prompt+and+languagemodel+pro
  • Network accessline 278
    *Applies to: Prompt API, as it's the only API that supports [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api).*
  • Network accessline 279
    schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api).*
  • Network accessline 284
    **Don't:** Enforce strict character limits like `maxLength: 125` using [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api). When a
  • Network accessline 285
    [structured output schemas](https://developer.chrome.com/docs/ai/structured-output-for-prompt-api). When a

skills/modern-web-guidance/guides/built-in-ai/summarizer.md

  • Network accessline 129
    <iframe src="https://example.com/" allow="summarizer"></iframe>

skills/modern-web-guidance/guides/built-in-ai/translator.md

  • Network accessline 159
    <iframe src="https://example.com/" allow="translator"></iframe>

skills/modern-web-guidance/guides/css/atrule-support-conditionals.md

  • Network accessline 92
    {# Testcase: https://codepen.io/leaverou/pen/KwWzpVr #}

skills/modern-web-guidance/guides/forms/custom-select-picker-layouts.md

  • Network accessline 131
    <!-- See https://github.com/GoogleChrome/modern-web-guidance-src/pull/960#pullrequestreview-4880620093 -->

skills/modern-web-guidance/guides/forms/forms.md

  • Network accessline 237
    e.preventDefault();   const data = new FormData(form);   // fetch('/submit', { method: 'POST', body: data });
  • Network accessline 238
    const data = new FormData(form);   // fetch('/submit', { method: 'POST', body: data }); });
  • Network accessline 239
    // fetch('/submit', { method: 'POST', body: data });

skills/modern-web-guidance/guides/forms/sms-otp-form.md

  • Network accessline 72
    - **Include human-readable text first**: Always start the SMS with a clear human-readable sentence containing the code so users typing it manually on another device can read it easily. - **Place `@<domain> #<otp>` on the very last line**: T
  • Network accessline 73
    - **Place `@<domain> #<otp>` on the very last line**: The `@` character must be the first character of the final line, with no trailing lines or signature text after it. - **Use only the host domain**: Do not include a URL scheme (`https://
  • Network accessline 74
    - **Use only the host domain**: Do not include a URL scheme (`https://` or `http://`), port (`:8080`), or path (`/verify`) in the `@domain` token.
  • Network accessline 79
    The WebOTP API (`OTPCredential`) requires a Secure Context (`https://` in production, or `http://localhost` during local development). Instead of pasting a disconnected `DOMContentLoaded` script that queries the DOM and calls `form.submit()
  • Network accessline 84
    - A new SMS code is requested ("Resend code"), aborting the previous controller before creating a new one.     - The verification component, dialog, or route unmounts. - **Trigger the application's submission handler (`form.requestSubmit()`
  • Network accessline 86
    - **Trigger the application's submission handler (`form.requestSubmit()`)**: When `navigator.credentials.get()` resolves with `otp`, set `otpInput.value = otp.code` and call `form.requestSubmit()` (or invoke your verification function direc
  • Network accessline 139
    event.preventDefault();   const formData = new FormData(otpForm);   // await fetch(otpForm.action, { method: 'POST', body: formData });
  • Network accessline 140
    const formData = new FormData(otpForm);   // await fetch(otpForm.action, { method: 'POST', body: formData }); });
  • Network accessline 141
    // await fetch(otpForm.action, { method: 'POST', body: formData });
  • Network accessline 163
    Permissions-Policy: otp-credentials=(self "https://bank.example")
  • Network accessline 169
    <iframe   src="https://bank.example/verify"
  • Network accessline 170
    src="https://bank.example/verify"
  • Network accessline 176
    Inside the `<iframe>` document served by `https://bank.example`, run the same `<form>` markup and `navigator.credentials.get({ otp: { transport: ['sms'] }, signal: ac.signal })` verification lifecycle shown above.

skills/modern-web-guidance/guides/html/html.md

  • Network accessline 94
    <!-- Quote with attribution using Figure --> <figure>   <blockquote cite="https://html.spec.whatwg.org/">
  • Network accessline 95
    <figure>   <blockquote cite="https://html.spec.whatwg.org/">     <p>The figure element represents some flow content, optionally with a caption, that is self-contained and is typically referenced as a single unit from the main flow of the do
  • Network accessline 96
    <blockquote cite="https://html.spec.whatwg.org/">

skills/modern-web-guidance/guides/js/calculate-event-differentials.md

  • Network accessline 103
    if (typeof Temporal === 'undefined') {     // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');
  • Network accessline 104
    // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');     globalThis.Temporal = module.Temporal;
  • Network accessline 105
    const module = await import('https://esm.sh/temporal-polyfill');

skills/modern-web-guidance/guides/js/capture-location-agnostic-data.md

  • Network accessline 140
    if (typeof Temporal === 'undefined') {     // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');
  • Network accessline 141
    // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');     globalThis.Temporal = module.Temporal;
  • Network accessline 142
    const module = await import('https://esm.sh/temporal-polyfill');

skills/modern-web-guidance/guides/js/coordinate-global-events.md

  • Network accessline 71
    if (typeof Temporal === 'undefined') {     // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');
  • Network accessline 72
    // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');     globalThis.Temporal = module.Temporal;
  • Network accessline 73
    const module = await import('https://esm.sh/temporal-polyfill');

skills/modern-web-guidance/guides/js/sort-high-precision-timestamps.md

  • Network accessline 83
    if (typeof Temporal === 'undefined') {     // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');
  • Network accessline 84
    // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');     globalThis.Temporal = module.Temporal;
  • Network accessline 85
    const module = await import('https://esm.sh/temporal-polyfill');

skills/modern-web-guidance/guides/js/support-global-calendar-systems.md

  • Network accessline 94
    if (typeof Temporal === 'undefined') {     // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');
  • Network accessline 95
    // Load the polyfill conditionally     const module = await import('https://esm.sh/temporal-polyfill');     globalThis.Temporal = module.Temporal;
  • Network accessline 96
    const module = await import('https://esm.sh/temporal-polyfill');

skills/modern-web-guidance/guides/performance/batch-analytics-events.md

  • Network accessline 116
    init.headers       ) {         fetch(url, Object.assign({}, init, {keepalive: true}));
  • Network accessline 117
    ) {         fetch(url, Object.assign({}, init, {keepalive: true}));         activated = true;
  • Network accessline 118
    fetch(url, Object.assign({}, init, {keepalive: true}));

skills/modern-web-guidance/guides/performance/conditional-async-dependencies.md

  • Network accessline 47
    * **DO NOT place sibling static imports in an entry file** (for example, `import './conditionally-load-polyfill.js'; import './app.js';`). Per the ECMAScript module evaluation specification, top-level `await` only suspends the parent module
  • Network accessline 48
    * **DO NOT import the top-level `await` module from multiple sibling modules simultaneously** (for example, having both `a.js` and `b.js` statically import `./conditionally-load-polyfill.js`). While [Safari 27 fixed WebKit's module loader](
  • Network accessline 71
    While basic top-level `await` has been supported across major browsers since 2021 (Chrome 89, Edge 89, Firefox 89, and Safari 15), it only reached full spec compliance in [Safari 27](https://webkit.org/blog/18227/fixing-top-level-await-in-s

skills/modern-web-guidance/guides/performance/deprioritize-background-fetches.md

  • Network accessline 7
    1. **Identify background requests**: Determine which `fetch()` calls are for non-essential data that doesn't impact the immediate user experience.
  • Network accessline 8
    2. **Apply fetch priority**: Add the `priority: 'low'` option to the `fetch()` initialization object.
  • Network accessline 13
    // Use high priority (default) for critical UI updates const criticalData = await fetch('/api/data');
  • Network accessline 14
    const criticalData = await fetch('/api/data');
  • Network accessline 16
    // Explicitly deprioritize background analytics fetch('/api/analytics', {
  • Network accessline 17
    fetch('/api/analytics', {

skills/modern-web-guidance/guides/performance/flicker-free-client-side-ab-testing.md

  • Network accessline 32
    -->   <script     src="https://cdn.example.com/experiment-sdk.js"
  • Network accessline 33
    <script     src="https://cdn.example.com/experiment-sdk.js"     async
  • Network accessline 34
    src="https://cdn.example.com/experiment-sdk.js"
  • Network accessline 52
    <link     rel="stylesheet"     href="https://cdn.example.com/experiment-variant-b.css"
  • Network accessline 53
    rel="stylesheet"     href="https://cdn.example.com/experiment-variant-b.css"     blocking="render"
  • Network accessline 54
    href="https://cdn.example.com/experiment-variant-b.css"
  • Network accessline 71
    <script type="module" blocking="render">     // Fetch the experiment configuration from your testing platform.     const config = await fetch('/api/experiment?id=homepage-cta')
  • Network accessline 72
    // Fetch the experiment configuration from your testing platform.     const config = await fetch('/api/experiment?id=homepage-cta')       .then(res => res.json());
  • Network accessline 73
    const config = await fetch('/api/experiment?id=homepage-cta')
  • Network accessline 120
    -->   <script     src="https://cdn.example.com/experiment-sdk.js"
  • Network accessline 121
    <script     src="https://cdn.example.com/experiment-sdk.js"     async
  • Network accessline 122
    src="https://cdn.example.com/experiment-sdk.js"

skills/modern-web-guidance/guides/performance/full-session-analytics.md

  • Network accessline 76
    The recommended fallback strategy is to use the polyfill below, which internally handles unsupporting browsers using `fetch()` with `keepalive` or `navigator.sendBeacon()`. Your own code MUST call `fetchLater()` directly — never call `fetch
  • Network accessline 97
    init.headers       ) {         fetch(url, Object.assign({}, init, {keepalive: true}));
  • Network accessline 98
    ) {         fetch(url, Object.assign({}, init, {keepalive: true}));         activated = true;
  • Network accessline 99
    fetch(url, Object.assign({}, init, {keepalive: true}));

skills/modern-web-guidance/guides/performance/interaction-paint-timing.md

  • Network accessline 5
    - **`LargestContentfulPaint` (`largest-contentful-paint`)** only measures the initial ("hard") document load and stops emitting entries as soon as the user first interacts with the page. - **`PerformanceEventTiming` and `event` / Interactio
  • Network accessline 6
    - **`PerformanceEventTiming` and `event` / Interaction to Next Paint (INP)** measures input responsiveness up to the *very next frame* (such as a button active state or loading spinner), but does not track subsequent asynchronous paints—suc

skills/modern-web-guidance/guides/performance/out-of-order-html-streaming.md

  • Network accessline 101
    const main = document.querySelector('main'); const response = await fetch('/api/partial-update');
  • Network accessline 102
    const response = await fetch('/api/partial-update');

skills/modern-web-guidance/guides/performance/performance.md

  • Network accessline 144
    <!-- 1. Place third-party scripts near the end of the page with the defer attribute --> <script defer src="http://www.example.com/third-party.js"></script>
  • Network accessline 145
    <script defer src="http://www.example.com/third-party.js"></script>
  • Network accessline 242
    <!-- DO: Use native lazy loading for below the fold iframes --> <iframe src="https://example.com/map" width="800" height="600" loading="lazy" title="Example Map"></iframe>
  • Network accessline 243
    <iframe src="https://example.com/map" width="800" height="600" loading="lazy" title="Example Map"></iframe>

skills/modern-web-guidance/guides/performance/schedule-tasks-by-priority.md

  • Network accessline 43
    // DO: Conditionally load the polyfill for browsers that need it   const script = document.createElement('script');   script.src = 'https://unpkg.com/scheduler-polyfill';
  • Network accessline 44
    const script = document.createElement('script');   script.src = 'https://unpkg.com/scheduler-polyfill';   script.onload = () => {
  • Network accessline 45
    script.src = 'https://unpkg.com/scheduler-polyfill';

skills/modern-web-guidance/guides/privacy/privacy.md

  • Network accessline 138
    <!-- No JS SDK required --> <a href="https://x.com/intent/tweet?text=Check%20this%20out&url=https%3A%2F%2Fexample.com"
  • Network accessline 139
    <a href="https://x.com/intent/tweet?text=Check%20this%20out&url=https%3A%2F%2Fexample.com"
  • Network accessline 147
    <div id="video-container" data-video-id="abc123">   <img src="https://img.youtube.com/vi/abc123/maxresdefault.jpg" alt="Play Video" id="play-btn">
  • Network accessline 148
    <img src="https://img.youtube.com/vi/abc123/maxresdefault.jpg" alt="Play Video" id="play-btn">
  • Network accessline 153
    const container = document.getElementById('video-container');   const videoId = container.dataset.videoId;   container.innerHTML = `<iframe src="https://www.youtube-nocookie.com/embed/${videoId}?autoplay=1" allowfullscreen></iframe>`;
  • Network accessline 154
    const videoId = container.dataset.videoId;   container.innerHTML = `<iframe src="https://www.youtube-nocookie.com/embed/${videoId}?autoplay=1" allowfullscreen></iframe>`; });
  • Network accessline 155
    container.innerHTML = `<iframe src="https://www.youtube-nocookie.com/embed/${videoId}?autoplay=1" allowfullscreen></iframe>`;
  • Network accessline 164
    identity: {       providers: [{         configURL: "https://idp.example/fedcm.json",
  • Network accessline 165
    providers: [{         configURL: "https://idp.example/fedcm.json",         clientId: "rp-client-id-123",
  • Network accessline 166
    configURL: "https://idp.example/fedcm.json",

skills/modern-web-guidance/guides/pwa/migrate-web-app-origin.md

  • Access to secretsline 11
    [Credential-related source omitted]
  • Network accessline 34
    "migrate_from": [     {       "id": "https://old-app.example.com/"
  • Network accessline 35
    {       "id": "https://old-app.example.com/"     }
  • Network accessline 36
    "id": "https://old-app.example.com/"
  • Network accessline 46
    File location: `https://old-app.example.com/.well-known/web-app-origin-association`
  • Network accessline 49
    {   "https://new-app.example.com": {
  • Network accessline 50
    "https://new-app.example.com": {
  • Network accessline 62
    "migrate_to": [     {       "id": "https://new-app.example.com/",
  • Network accessline 63
    {       "id": "https://new-app.example.com/",       "install_url": "https://new-app.example.com/demo.html"
  • Network accessline 64
    "id": "https://new-app.example.com/",
  • Network accessline 65
    "install_url": "https://new-app.example.com/demo.html"
  • Network accessline 77
    "migrate_from": [     {       "id": "https://old-app.example.com/",
  • Network accessline 78
    {       "id": "https://old-app.example.com/",       "behavior": "force"
  • Network accessline 79
    "id": "https://old-app.example.com/",

skills/modern-web-guidance/guides/security/local-network-access.md

  • Network accessline 9
    Because `localhost` (`127.0.0.1` and `[::1]`) is already in the most private (`loopback`) address space, serving your web app from `http://localhost` during local development will **not** trigger LNA checks by default. To test LNA prompts a
  • Network accessline 11
    **MANDATORY:** Serve any web application that initiates local or loopback network requests from a **Secure Context (`https://`)**. Local Network Access permissions are denied automatically in insecure (`http://`) top-level contexts.
  • Network accessline 56
    ### 2. Declare `targetAddressSpace` in `fetch()` and `Request`
  • Network accessline 58
    When an `https://` page requests an `http://` endpoint on the local network or loopback interface, specify `targetAddressSpace: 'local'` or `targetAddressSpace: 'loopback'` in the `fetch()` or `Request` options.
  • Network accessline 60
    Explicitly setting `targetAddressSpace` does two critical things: 1. **Mixed Content Exemption**: Mixed Content checks run *before* DNS resolution. Declaring `targetAddressSpace: 'local'` (or `'loopback'`) informs the browser ahead of DNS r
  • Network accessline 61
    1. **Mixed Content Exemption**: Mixed Content checks run *before* DNS resolution. Declaring `targetAddressSpace: 'local'` (or `'loopback'`) informs the browser ahead of DNS resolution that an `http://` URL (including a custom DNS hostname t
  • Network accessline 67
    * Example endpoint URL is illustrative; replace with your device's address.  */ export async function fetchLocalDeviceStatus(deviceUrl = 'http://192.168.1.100:8080/api/status') {
  • Network accessline 68
    */ export async function fetchLocalDeviceStatus(deviceUrl = 'http://192.168.1.100:8080/api/status') {   const request = new Request(deviceUrl, {
  • Network accessline 69
    export async function fetchLocalDeviceStatus(deviceUrl = 'http://192.168.1.100:8080/api/status') {
  • Network accessline 77
    const response = await fetch(request);
  • Network accessline 86
    * Example loopback port is illustrative; replace with your service's port.  */ export async function fetchLoopbackDaemon(daemonUrl = 'http://127.0.0.1:45678/health') {
  • Network accessline 87
    */ export async function fetchLoopbackDaemon(daemonUrl = 'http://127.0.0.1:45678/health') {   const request = new Request(daemonUrl, {
  • Network accessline 88
    export async function fetchLoopbackDaemon(daemonUrl = 'http://127.0.0.1:45678/health') {
  • Network accessline 96
    const response = await fetch(request);
  • Network accessline 108
    - **`WebSocket`**: The `WebSocket(url, protocols)` constructor only accepts a subprotocol string or array as its second argument—do **not** pass a `{ targetAddressSpace }` options object, which throws a `SyntaxError`. Instead, the browser i
  • Network accessline 109
    - **`WebTransport`**: Because `WebTransport` strictly requires `https://` (HTTP/3 over QUIC with TLS or `serverCertificateHashes` for local self-signed certificates), it never triggers Mixed Content blocks and does not accept a `targetAddre
  • Network accessline 124
    * Opens a WebTransport session to a local network endpoint using a pinned self-signed certificate hash.  */ export async function openLocalWebTransport(wtUrl = 'https://192.168.1.100:4433/wt', certSha256Bytes) {
  • Network accessline 125
    */ export async function openLocalWebTransport(wtUrl = 'https://192.168.1.100:4433/wt', certSha256Bytes) {   const transport = new WebTransport(wtUrl, {
  • Network accessline 126
    export async function openLocalWebTransport(wtUrl = 'https://192.168.1.100:4433/wt', certSha256Bytes) {
  • Network accessline 148
    <!-- Delegate granular local-network and loopback-network permissions to the embedded iframe --> <iframe   src="https://setup.partner.example.com/device-bridge"
  • Network accessline 149
    <iframe   src="https://setup.partner.example.com/device-bridge"   allow="local-network; loopback-network"
  • Network accessline 150
    src="https://setup.partner.example.com/device-bridge"
  • Network accessline 159
    Permissions-Policy: local-network=(self "https://setup.partner.example.com"), loopback-network=(self "https://setup.partner.example.com")
  • Network accessline 170
    1. **Permission Query Fallback**: Wrap `navigator.permissions.query({ name: permissionName })` in a `try / catch`. If the browser throws a `TypeError` because `'local-network'` or `'loopback-network'` is an unrecognized `PermissionName`, tr
  • Network accessline 172
    3. **Graceful Rejection Handling**: Always wrap `fetch()`, `WebSocket` error events, and `transport.ready` in error handlers that catch `TypeError` / connection failures and present clear remediation steps (checking that the local device is

skills/modern-web-guidance/guides/security/passkey-authentication.md

  • Network accessline 72
    - `NotAllowedError`: The user cancelled or timed out the passkey login prompt.     - `AbortError`: The authentication request was cancelled programmatically. 5.  **Call Signal API**: Wrap server verification `fetch()` call in a try/catch bl
  • Network accessline 73
    - `AbortError`: The authentication request was cancelled programmatically. 5.  **Call Signal API**: Wrap server verification `fetch()` call in a try/catch block:     - Show an error message for the user to understand what went wrong.
  • Network accessline 74
    5.  **Call Signal API**: Wrap server verification `fetch()` call in a try/catch block:

skills/modern-web-guidance/guides/security/passkey-management.md

  • Access to secretsline 156
    [Credential-related source omitted]
  • Network accessline 165
    https://raw.githubusercontent.com/passkeydeveloper/passkey-authenticator-aaguids/refs/heads/main/combined_aaguid.json
  • Network accessline 227
    <script type="module">    if (!PublicKeyCredential.parseRequestOptionsFromJSON) {       await import('https://unpkg.com/webauthn-polyfills');
  • Network accessline 228
    if (!PublicKeyCredential.parseRequestOptionsFromJSON) {       await import('https://unpkg.com/webauthn-polyfills');     }
  • Network accessline 229
    await import('https://unpkg.com/webauthn-polyfills');

skills/modern-web-guidance/guides/security/passkey-reauthentication.md

  • Network accessline 62
    const optionsResponse = await fetch("/api/reauth/options", {
  • Network accessline 75
    if (credential) {       const encodedCredential = credential.toJSON();       const verifyResponse = await fetch("/api/reauth/verify", {
  • Network accessline 76
    const encodedCredential = credential.toJSON();       const verifyResponse = await fetch("/api/reauth/verify", {         method: "POST",
  • Network accessline 77
    const verifyResponse = await fetch("/api/reauth/verify", {

skills/modern-web-guidance/guides/security/passkey-registration.md

  • Network accessline 95
    - `SecurityError`: Secure origins (HTTPS) or RP ID mismatch errors (configuration issues). 4.  **Try/Catch Segregation for Signal API**:     - Wrap server verification `fetch()` call in a try/catch block. Call `signalUnknownCredential()` wh
  • Network accessline 97
    - Wrap server verification `fetch()` call in a try/catch block. Call `signalUnknownCredential()` when the server verification fetch fails (any status `response.ok === false` or network throws).

skills/modern-web-guidance/guides/security/passkeys.md

  • Network accessline 7
    Passkeys rely on the Web Authentication API (WebAuthn), which imposes strict cross-cutting security constraints that must be satisfied before any implementation attempt: *   **Secure Contexts**: WebAuthn methods (`navigator.credentials.crea
  • Network accessline 8
    *   **Secure Contexts**: WebAuthn methods (`navigator.credentials.create` and `navigator.credentials.get`) are strictly gated behind Secure Contexts. Applications MUST run on `https://` in production, or `http://localhost` for local develop
  • Access to secretsline 13
    [Credential-related source omitted]

skills/modern-web-guidance/guides/security/quick-sign-ins.md

  • Network accessline 77
    async function authenticateWithImmediateUi() {   const optionsResponse = await fetch('/api/login/options', { method: 'POST' });
  • Network accessline 78
    const optionsResponse = await fetch('/api/login/options', { method: 'POST' });
  • Network accessline 96
    if (cred.type === 'public-key') {     const encoded = cred.toJSON();     const verifyResponse = await fetch('/api/login/verify', {
  • Network accessline 97
    const encoded = cred.toJSON();     const verifyResponse = await fetch('/api/login/verify', {       method: 'POST',
  • Network accessline 98
    const verifyResponse = await fetch('/api/login/verify', {
  • Network accessline 118
    if (cred.type === 'password') {     const verifyResponse = await fetch('/api/login/password', {
  • Network accessline 119
    const verifyResponse = await fetch('/api/login/password', {

skills/modern-web-guidance/guides/security/restrict-outbound-connections.md

  • Network accessline 3
    The `Connection-Allowlist` HTTP response header restricts a document or worker to communicating only with an explicit list of network endpoints. Unlike Content Security Policy (CSP)—which requires maintaining separate per-resource directive
  • Network accessline 7
    1. **Serialize the allowlist as an RFC 9651 Inner List `(...)`**: Format `Connection-Allowlist` (or `Connection-Allowlist-Report-Only`) as a single parenthesized list of space-separated items. Include the unquoted token `response-origin` to
  • Network accessline 8
    2. **Scope middleware by `Sec-Fetch-Dest` and cover workers**: Browsers only honor `Connection-Allowlist` on document/navigation responses and worker script responses (`Sec-Fetch-Dest` values `document`, `iframe`, `worker`, `sharedworker`, 
  • Network accessline 10
    4. **Account for default redirect and WebRTC blocking, and handle client errors**: By default, `Connection-Allowlist` blocks all `3xx` HTTP redirects (`redirects=block`, even when redirecting between allowlisted or same-origin URLs) and all
  • Network accessline 15
    Vary: Sec-Fetch-Dest Reporting-Endpoints: conn-reports="https://app.example.com/api/security-reports"
  • Network accessline 16
    Reporting-Endpoints: conn-reports="https://app.example.com/api/security-reports"
  • Network accessline 17
    Connection-Allowlist: (response-origin "https://api.example.com" "https://realtime.example.com" "https://*.cdn.example.com/*"); report-to=conn-reports
  • Network accessline 18
    Connection-Allowlist-Report-Only: (response-origin "https://api.example.com/v2/*"); report-to=conn-reports
  • Network accessline 73
    const {     secFetchDest = 'document',     patterns = ['https://api.example.com', 'https://realtime.example.com', 'https://*.cdn.example.com/*'],
  • Network accessline 74
    secFetchDest = 'document',     patterns = ['https://api.example.com', 'https://realtime.example.com', 'https://*.cdn.example.com/*'],     reportOnlyPatterns,
  • Network accessline 75
    patterns = ['https://api.example.com', 'https://realtime.example.com', 'https://*.cdn.example.com/*'],
  • Network accessline 76
    reportOnlyPatterns,     reportEndpointName = 'conn-reports',     reportEndpointUrl = 'https://app.example.com/api/security-reports',
  • Network accessline 77
    reportEndpointName = 'conn-reports',     reportEndpointUrl = 'https://app.example.com/api/security-reports',     redirects = 'block',
  • Network accessline 78
    reportEndpointUrl = 'https://app.example.com/api/security-reports',
  • Network accessline 117
    export async function fetchWithPolicyHandling(url, { statusElement, ...fetchOptions } = {}) {   try {     const response = await fetch(url, fetchOptions);
  • Network accessline 118
    try {     const response = await fetch(url, fetchOptions);     if (!response.ok) throw new Error(`HTTP ${response.status}`);
  • Network accessline 119
    const response = await fetch(url, fetchOptions);
  • Network accessline 138
    - **DO** format `Connection-Allowlist` as a single RFC 9651 Inner List `(...)` of space-separated items. If a non-empty `Connection-Allowlist` header fails top-level Structured Field parsing (for example, omitting `(...)` or using single qu
  • Network accessline 139
    - **DO** omit the trailing slash on origin-wide URL patterns (`"https://api.example.com"`) or use an explicit wildcard (`"https://api.example.com/*"`) so subpaths like `/v1/users` are permitted. Strip trailing slashes added by `new URL(orig
  • Network accessline 140
    - **DO** allowlist `WebSocket` (`ws://` and `wss://`) endpoints using `"http://..."` and `"https://..."` patterns in `Connection-Allowlist`, because the browser normalizes WebSocket schemes to HTTP/HTTPS before matching.
  • Network accessline 154
    - **Additive defense-in-depth**: Supporting browsers enforce both policies simultaneously—`Connection-Allowlist` blocks non-CSP exfiltration channels (`dns-prefetch`, `preconnect`, WebRTC, and redirects), while CSP restricts `fetch()`, subr
  • Network accessline 155
    - **Cover `form-action` and `worker-src` explicitly**: In CSP, `default-src` does **not** fall back for `<form action>` submissions; always include `form-action` explicitly. Include `worker-src 'self'` (excluding `blob:`) so restricted page
  • Network accessline 157
    - **Include `wss://` in CSP `connect-src`**: While `Connection-Allowlist` matches `wss://` connections against `"https://..."` patterns, CSP `connect-src` in cross-browser environments should explicitly list `wss://` origins when WebSockets
  • Network accessline 160
    Content-Security-Policy: default-src 'self'; connect-src 'self' https://api.example.com https://realtime.example.com wss://realtime.example.com; img-src 'self' https://*.cdn.example.com data: blob:; form-action 'self'; worker-src 'self'; ob
  • Network accessline 165
    <meta   http-equiv="Content-Security-Policy"   content="default-src 'self'; connect-src 'self' https://api.example.com https://realtime.example.com wss://realtime.example.com; img-src 'self' https://*.cdn.example.com data: blob:; form-actio
  • Network accessline 166
    http-equiv="Content-Security-Policy"   content="default-src 'self'; connect-src 'self' https://api.example.com https://realtime.example.com wss://realtime.example.com; img-src 'self' https://*.cdn.example.com data: blob:; form-action 'self'
  • Network accessline 167
    content="default-src 'self'; connect-src 'self' https://api.example.com https://realtime.example.com wss://realtime.example.com; img-src 'self' https://*.cdn.example.com data: blob:; form-action 'self'; worker-src 'self'; object-src 'none';

skills/modern-web-guidance/guides/security/secure-external-subresources.md

  • Network accessline 9
    - **Compute digests at build or release time, never from live untrusted responses**: Generate integrity hashes during your build or release step from known-good local asset bytes (or copy the official digest published by the package author)
  • Network accessline 10
    - **Use `sha384-` by default**: Format integrity metadata as `<algorithm>-<base64-digest>` using `sha384-` (recommended default), `sha512-`, or `sha256-`. - **Pin external subresources to immutable, versioned URLs**: Always reference third-
  • Network accessline 11
    - **Pin external subresources to immutable, versioned URLs**: Always reference third-party assets using immutable, version-pinned or content-addressed URLs (such as `https://cdn.example.com/ui@2.4.0/app.min.js`) rather than mutable floating
  • Network accessline 48
    <link   rel="stylesheet"   href="https://cdn.example.com/ui@2.4.0/styles.css"
  • Network accessline 49
    rel="stylesheet"   href="https://cdn.example.com/ui@2.4.0/styles.css"   integrity="sha384-bs0EksOYBbU/g0IAHMXbSyH1Mgw83GKn+EZlSI+VE+zVchXmSbLwhVLrPzsOWnc5"
  • Network accessline 50
    href="https://cdn.example.com/ui@2.4.0/styles.css"
  • Network accessline 56
    <!-- External script with SRI, anonymous CORS, and no referrer --> <script   src="https://cdn.example.com/ui@2.4.0/bundle.min.js"
  • Network accessline 57
    <script   src="https://cdn.example.com/ui@2.4.0/bundle.min.js"   integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
  • Network accessline 58
    src="https://cdn.example.com/ui@2.4.0/bundle.min.js"
  • Network accessline 65
    When fetching external subresources programmatically with `fetch()`, pass the matching `integrity`, `mode`, `credentials`, and `referrerPolicy` options (a digest mismatch rejects the promise with `TypeError`):
  • Network accessline 68
    const response = await fetch('https://cdn.example.com/ui@2.4.0/manifest.json', {
  • Network accessline 94
    @import url(   "https://cdn.example.com/theme@1.2.0/tokens.css"
  • Network accessline 95
    "https://cdn.example.com/theme@1.2.0/tokens.css"
  • Network accessline 102
    font-family: "BrandSans";   src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 103
    src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"     cross-origin(anonymous)
  • Network accessline 104
    "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 112
    .verified-graphic {   background-image: url(     "https://cdn.example.com/media@1.0.0/badge.svg"
  • Network accessline 113
    background-image: url(     "https://cdn.example.com/media@1.0.0/badge.svg"     cross-origin(anonymous)
  • Network accessline 114
    "https://cdn.example.com/media@1.0.0/badge.svg"
  • Network accessline 145
    font-family: "BrandSans";   /* 1. Parse-time fallback for browsers without url() modifier support */   src: url("https://cdn.example.com/fonts@1.0.0/brand-sans.woff2") format("woff2");
  • Network accessline 146
    /* 1. Parse-time fallback for browsers without url() modifier support */   src: url("https://cdn.example.com/fonts@1.0.0/brand-sans.woff2") format("woff2");   /* 2. Parse-time fallback for browsers supporting cross-origin() and referrer-pol
  • Network accessline 147
    src: url("https://cdn.example.com/fonts@1.0.0/brand-sans.woff2") format("woff2");
  • Network accessline 148
    /* 2. Parse-time fallback for browsers supporting cross-origin() and referrer-policy() */   src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 149
    src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"     cross-origin(anonymous)
  • Network accessline 150
    "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 154
    /* 3. Full protection in browsers supporting cross-origin(), referrer-policy(), and integrity() */   src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 155
    src: url(     "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"     cross-origin(anonymous)
  • Network accessline 156
    "https://cdn.example.com/fonts@1.0.0/brand-sans.woff2"
  • Network accessline 164
    .verified-graphic {   background-image: url("https://cdn.example.com/media@1.0.0/badge.svg");
  • Network accessline 165
    background-image: url("https://cdn.example.com/media@1.0.0/badge.svg");
  • Network accessline 166
    background-image: url(     "https://cdn.example.com/media@1.0.0/badge.svg"     cross-origin(anonymous)
  • Network accessline 167
    "https://cdn.example.com/media@1.0.0/badge.svg"
  • Network accessline 170
    );   background-image: url(     "https://cdn.example.com/media@1.0.0/badge.svg"
  • Network accessline 171
    background-image: url(     "https://cdn.example.com/media@1.0.0/badge.svg"     cross-origin(anonymous)
  • Network accessline 172
    "https://cdn.example.com/media@1.0.0/badge.svg"
  • Network accessline 187
    CSS.supports(       'background-image',       'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer))',
  • Network accessline 188
    'background-image',       'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer))',     );
  • Network accessline 189
    'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer))',
  • Network accessline 195
    CSS.supports(       'background-image',       'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91"))',
  • Network accessline 196
    'background-image',       'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91"))',     );
  • Network accessline 197
    'url("https://example.com/a.svg" cross-origin(anonymous) referrer-policy(no-referrer) integrity("sha384-Iw/0p59dP96nGTzHvf2XIfqcBwBW7RM6JfOij8uZxyg5azfNaOOUW8SQy6H/hU91"))',

skills/modern-web-guidance/guides/security/security.md

  • Network accessline 96
    X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com;
  • Network accessline 97
    Content-Security-Policy: frame-ancestors 'self' https://trusted-partner.com;
  • Network accessline 107
    // Receiver (Safe - traditional string check) window.addEventListener('message', (event) => {   if (event.origin !== 'https://trusted-origin.com') return;
  • Network accessline 108
    window.addEventListener('message', (event) => {   if (event.origin !== 'https://trusted-origin.com') return;   const data = event.data;
  • Network accessline 109
    if (event.origin !== 'https://trusted-origin.com') return;
  • Network accessline 116
    // Sender (Safe) targetWindow.postMessage({ action: 'update' }, 'https://trusted-origin.com');
  • Network accessline 117
    targetWindow.postMessage({ action: 'update' }, 'https://trusted-origin.com');
  • Network accessline 147
    Reporting-Endpoints: default="https://reports.example/default", main-endpoint="https://reports.example/main"
  • Network accessline 206
    Reporting-Endpoints: main-endpoint="https://reports.example/main"
  • Network accessline 212
    <script nonce="{RANDOM}" src="https://example.com/script.js"></script>
  • Network accessline 232
    headers.set('Reporting-Endpoints', 'main-endpoint="https://reports.example/main"');
  • Network accessline 242
    **Avoid**: - Broad scheme or domain allowlists (such as `https:` alone or `script-src https://cdn.example.com` without `'strict-dynamic'`) as the primary `script-src` protection — they are easily bypassed by open redirects, JSONP endpoints,
  • Network accessline 243
    - Broad scheme or domain allowlists (such as `https:` alone or `script-src https://cdn.example.com` without `'strict-dynamic'`) as the primary `script-src` protection — they are easily bypassed by open redirects, JSONP endpoints, and depend
  • Access to secretsline 286
    [Credential-related source omitted]
  • Network accessline 351
    <iframe src="https://trusted-video.com/player" allow="fullscreen; camera; focus-without-user-activation 'none'"></iframe>
  • Network accessline 360
    <script src="https://cdn.example.com/lib@1.0.0.js" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
  • Network accessline 371
    Access-Control-Allow-Origin: https://trusted-app.com

skills/modern-web-guidance/guides/security/trusted-types.md

  • Dangerous shell operationline 74
    - **Script:** `<script>` text content, `eval()`

skills/modern-web-guidance/guides/security/validate-origins.md

  • Network accessline 3
    While comparing `event.origin` against a fixed, port-normalized string literal (such as `event.origin === 'https://app.example.com'`) works for simple allowlists, manual string comparisons and regular expressions break down when validating 
  • Network accessline 5
    - **Prefix and substring spoofing:** Checking `url.startsWith('https://app.example.com')` is bypassed by `'https://app.example.com.attacker.example'`.
  • Network accessline 6
    - **Unnormalized URLs:** Full URLs with paths, query strings, or explicit default ports (`'https://app.example.com:443/path'`) do not match `'https://app.example.com'` under string equality without first parsing and normalizing.
  • Network accessline 14
    - **Use `isSameOrigin()` for strict privilege boundaries:** Require an exact `(scheme, host, port)` match when handling cross-window `postMessage` commands (such as an embedded checkout or auth popup) or deciding whether to attach credentia
  • Network accessline 15
    - **Use `isSameSite()` for cross-subdomain navigation and link classification:** Allow any subdomain or port sharing the same scheme and registrable domain when validating post-login redirect URLs (`?returnTo=https://billing.example.co.uk/o
  • Network accessline 22
    - **Both sides must be `Origin` instances:** `isSameOrigin(other)` and `isSameSite(other)` only accept an `Origin` object—passing a raw string throws a `TypeError`. - **Supported `Origin.from()` inputs:**   - Serialized URL strings (for exa
  • Network accessline 23
    - **Supported `Origin.from()` inputs:**   - Serialized URL strings (for example, `'https://app.example.com:443/path'`). Note that any invalid URL string—for instance `'example'`, or the `'null'` string serialized by `event.origin` for opaqu
  • Network accessline 24
    - Serialized URL strings (for example, `'https://app.example.com:443/path'`). Note that any invalid URL string—for instance `'example'`, or the `'null'` string serialized by `event.origin` for opaque origins—causes `Origin.from()` to throw 
  • Network accessline 30
    // Replace with your application's trusted origin(s) const TRUSTED_ORIGIN = Origin.from('https://app.example.com');
  • Network accessline 31
    const TRUSTED_ORIGIN = Origin.from('https://app.example.com');
  • Network accessline 64
    When validating redirect targets (such as `?returnTo=` parameters) or internal links across subdomains of the same registrable domain (for example, `https://app.example.co.uk` and `https://billing.example.co.uk:8443`), use `isSameSite()`:
  • Network accessline 66
    - `isSameSite()` performs a **schemeful same-site** comparison: `https://sub.example.com` and `http://sub.example.com` are **not** same-site because their schemes differ.
  • Network accessline 67
    - `isSameSite()` uses the browser's built-in **Public Suffix List**, so distinct tenants on shared public suffixes (such as `https://tenant-a.github.io` and `https://tenant-b.github.io`, or `https://a.co.uk` and `https://b.co.uk`) evaluate 
  • Network accessline 70
    // Replace with your application's primary origin const APP_ORIGIN = Origin.from('https://app.example.co.uk');
  • Network accessline 71
    const APP_ORIGIN = Origin.from('https://app.example.co.uk');
  • Network accessline 81
    // true: same scheme (https) and same registrable domain (example.co.uk) isAllowedSameSiteUrl('https://billing.example.co.uk:8443/checkout');
  • Network accessline 82
    isAllowedSameSiteUrl('https://billing.example.co.uk:8443/checkout');
  • Network accessline 84
    // false: scheme downgrade (http vs. https) is rejected by schemeful same-site isAllowedSameSiteUrl('http://billing.example.co.uk/checkout');
  • Network accessline 85
    isAllowedSameSiteUrl('http://billing.example.co.uk/checkout');
  • Network accessline 136
    - **Same-origin fallback (tuple origins):** Extract the URL string (using `event.origin` for `MessageEvent` objects or `candidate.href` for link elements), parse both the candidate and trusted URLs with `new URL()`, reject `"null"` opaque o
  • Network accessline 141
    // Replace with your trusted reference URL and known registrable domain const TRUSTED_URL = 'https://app.example.com';
  • Network accessline 142
    const TRUSTED_URL = 'https://app.example.com';

skills/modern-web-guidance/guides/security/verify-email-ownership.md

  • Network accessline 16
    1. **Provide the Origin Trial token** on the page hosting the form using either the `Origin-Trial` HTTP response header or a `<meta http-equiv="origin-trial">` element.    - **Third-party origin trials:** Embedded identity SDKs can inject a
  • Network accessline 17
    - **Third-party origin trials:** Embedded identity SDKs can inject a third-party trial token, provided the Origin Trial registrant origin matches the issuer domain (same-site with the issuer, such as `https://issuer.example`).
  • Network accessline 53
    // Replace with your public relying-party origin const RP_ORIGIN = 'https://rp.example.com';
  • Network accessline 54
    const RP_ORIGIN = 'https://rp.example.com';
  • Network accessline 123
    const domain = submittedEmail.split('@')[1]; const txtRecords = (await dns.resolveTxt(`_email-verification.${domain}`)).map((r) => r.join('')); if (!txtRecords.some((txt) => txt.startsWith('iss=') && `https://${txt.slice(4).trim()}` === iss
  • Network accessline 124
    const txtRecords = (await dns.resolveTxt(`_email-verification.${domain}`)).map((r) => r.join('')); if (!txtRecords.some((txt) => txt.startsWith('iss=') && `https://${txt.slice(4).trim()}` === iss)) {   throw new Error(`Issuer "${iss}" is no
  • Network accessline 125
    if (!txtRecords.some((txt) => txt.startsWith('iss=') && `https://${txt.slice(4).trim()}` === iss)) {
  • Network accessline 129
    const discoveryUrl = new URL('/.well-known/email-verification', iss); if (discoveryUrl.protocol !== 'https:') throw new Error('Issuer must use HTTPS.'); const metadata = await (await fetch(discoveryUrl)).json();
  • Network accessline 130
    if (discoveryUrl.protocol !== 'https:') throw new Error('Issuer must use HTTPS.'); const metadata = await (await fetch(discoveryUrl)).json(); if (metadata.issuer !== iss || !metadata.jwks_uri?.startsWith('https://')) {
  • Network accessline 131
    const metadata = await (await fetch(discoveryUrl)).json();

skills/modern-web-guidance/guides/ui-atoms/icons.md

  • Network accessline 19
    If a page renders thousands of icons at once, benchmark the actual page and assets. In a stress test, inline SVG had a small performance advantage at that scale, but results depend on the browser and implementation. [Cloud Four's SVG icon s
  • Network accessline 56
    --icon-style-size: 1em;   --icon-style-spacing: 0.4em;   --icon-trash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M3 6h18M8 6V4a2 2 0
  • Network accessline 57
    --icon-style-spacing: 0.4em;   --icon-trash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2
  • Network accessline 58
    --icon-trash: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpath d='M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0-1 14a2 2 0 0 1-2 2H7a2 2 0
  • Network accessline 59
    --icon-favorite: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3E%3Cpath d='M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z'/%3E%3C/svg
  • Network accessline 252
    Safari has two rendering bugs affecting icons: WebKit [#301609](https://bugs.webkit.org/show_bug.cgi?id=301609) can prevent them from appearing until user interaction, and [#320220](https://bugs.webkit.org/show_bug.cgi?id=320220) also affec

skills/modern-web-guidance/guides/ui-atoms/position-aware-tooltips.md

  • Network accessline 127
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 141
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 142
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 143
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");

skills/modern-web-guidance/guides/ui-atoms/viewport-aware-dropdowns.md

  • Network accessline 75
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 89
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 90
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 91
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 116
    <script type="module">   if (!("anchorName" in document.documentElement.style)) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  • Network accessline 117
    if (!("anchorName" in document.documentElement.style)) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");   }
  • Network accessline 118
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");

skills/modern-web-guidance/guides/ui-behaviors/animate-to-from-top-layer.md

  • Network accessline 211
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 225
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 226
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 227
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");

skills/modern-web-guidance/guides/ui-behaviors/custom-button-actions.md

  • Network accessline 91
    If the Invoker Commands API is not supported, the `command` event will not fire. For full support across all modern browsers, it is recommended to use the invokers-polyfill from https://github.com/keithamus/invokers-polyfill via `npm instal
  • Network accessline 107
    (async () => {     try {       await import('https://esm.run/invokers-polyfill');
  • Network accessline 108
    try {       await import('https://esm.run/invokers-polyfill');     } catch (err) {
  • Network accessline 109
    await import('https://esm.run/invokers-polyfill');

skills/modern-web-guidance/guides/ui-behaviors/declarative-dialog-popover-control.md

  • Network accessline 92
    // Conditionally load the invokers-polyfill from a CDN only in browsers lacking native support.   if (!('commandForElement' in HTMLButtonElement.prototype)) {     import('https://esm.run/invokers-polyfill');
  • Network accessline 93
    if (!('commandForElement' in HTMLButtonElement.prototype)) {     import('https://esm.run/invokers-polyfill');   }
  • Network accessline 94
    import('https://esm.run/invokers-polyfill');
  • Network accessline 105
    If the Invoker Commands API is not supported, the `command` event will not fire. For full support across all modern browsers, it is recommended to use the invokers-polyfill from https://github.com/keithamus/invokers-polyfill via `npm instal
  • Network accessline 121
    (async () => {     try {       await import('https://esm.run/invokers-polyfill');
  • Network accessline 122
    try {       await import('https://esm.run/invokers-polyfill');     } catch (err) {
  • Network accessline 123
    await import('https://esm.run/invokers-polyfill');
  • Network accessline 203
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 217
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 218
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 219
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");

skills/modern-web-guidance/guides/ui-behaviors/interest-triggered-action-previews.md

  • Network accessline 64
    if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {     // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");
  • Network accessline 65
    // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");   }
  • Network accessline 66
    await import("https://unpkg.com/interestfor@latest");

skills/modern-web-guidance/guides/ui-behaviors/interest-triggered-tooltips.md

  • Network accessline 75
    if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {     // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");
  • Network accessline 76
    // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");   }
  • Network accessline 77
    await import("https://unpkg.com/interestfor@latest");
  • Network accessline 113
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 127
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 128
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 129
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 160
    <script type="module">   if (!("anchorName" in document.documentElement.style)) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  • Network accessline 161
    if (!("anchorName" in document.documentElement.style)) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");   }
  • Network accessline 162
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");

skills/modern-web-guidance/guides/ui-behaviors/physics-based-easing.md

  • Network accessline 100
    This should only be initialized if native CSS support is missing.   */   import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {
  • Network accessline 101
    */   import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {     animate(".element", { transform: "scale(1.2)" }, {
  • Network accessline 102
    import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {

skills/modern-web-guidance/guides/ui-behaviors/swipe-to-remove.md

  • Network accessline 149
    is baked into the SVG so it contrasts with the red spacer background;      adjust if your background color is light. */   --action-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><
  • Network accessline 151
    --action-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M9 3v1H4v2h1v13a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V6h1V4h-5V3H9zm0 5h2v9H9V8zm4 0h2v9h-2V8z'/></svg>");

skills/modern-web-guidance/guides/ui-components/checkbox.md

  • Network accessline 32
    /* Reusable SVG assets */ :root {   --icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polylin
  • Network accessline 33
    :root {   --icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'>
  • Network accessline 34
    --icon-check: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'></polyline
  • Network accessline 35
    --icon-dash: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='4.5' stroke-linecap='round' stroke-linejoin='round'><line x1='5' y1='12' x2='19' y2='12'></line><

skills/modern-web-guidance/guides/ui-components/dialog.md

  • Network accessline 197
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 211
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 212
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 213
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");

skills/modern-web-guidance/guides/ui-components/hovercard.md

  • Network accessline 195
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 209
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 210
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 211
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 242
    if (!HTMLButtonElement.prototype.hasOwnProperty("interestForElement")) {     // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");
  • Network accessline 243
    // CDN link only used for example, prefer bundling.     await import("https://unpkg.com/interestfor@latest");   }
  • Network accessline 244
    await import("https://unpkg.com/interestfor@latest");

skills/modern-web-guidance/guides/ui-components/menu.md

  • Network accessline 349
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 363
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 364
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 365
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");

skills/modern-web-guidance/guides/ui-components/persistent-app-tours.md

  • Network accessline 64
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 78
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 79
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 80
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 107
    <script type="module">   if (!CSS.supports('anchor-name: --foo')) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");
  • Network accessline 108
    if (!CSS.supports('anchor-name: --foo')) {     await import("https://unpkg.com/@oddbird/css-anchor-positioning");   }
  • Network accessline 109
    await import("https://unpkg.com/@oddbird/css-anchor-positioning");

skills/modern-web-guidance/guides/ui-components/persistent-toast-notifications.md

  • Network accessline 23
    **Polyfill:** To support the `popover` attribute in older browsers, conditionally load [`@oddbird/popover-polyfill`](https://github.com/oddbird/popover-polyfill). **MANDATORY:** Feature detect by checking for the `popover` property on `HTML
  • Network accessline 37
    <script type="module">   if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 38
    if (!("popover" in HTMLElement.prototype)) {     import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");   }
  • Network accessline 39
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  • Network accessline 60
    * **Guidance:** Use the [CSS Anchor Positioning Polyfill](https://github.com/oddbird/css-anchor-positioning). For a non-polyfill fallback, default the tooltip to a fixed position at the bottom of the viewport using `@supports not (anchor-na

skills/modern-web-guidance/guides/visual-design/adapt-scrollbar-to-contrast-preferences.md

  • Network accessline 36
    - Do NOT animate or transition `scrollbar-color`. A [WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=311752) causes the scrollbar to flicker every time `scrollbar-color` changes.

skills/modern-web-guidance/guides/visual-design/apply-webgl-shaders.md

  • Network accessline 274
    # Embed <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>
  • Network accessline 275
    <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>

skills/modern-web-guidance/guides/visual-design/contrast-color.md

  • Network accessline 148
    1. Load this SVG filter definition. It must be added directly to the HTML document if you need to support Safari versions affected by [this WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=320118), which prevents external and data url re
  • Network accessline 151
    <!-- Technique from https://miunau.com/posts/dynamic-text-contrast-in-css/ -->
  • Network accessline 152
    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="0" style="display: none;">

skills/modern-web-guidance/guides/visual-design/dark-mode.md

  • Network accessline 104
    - Do NOT animate or transition `scrollbar-color`. A [WebKit bug](https://bugs.webkit.org/show_bug.cgi?id=311752) causes the scrollbar to flicker every time `scrollbar-color` changes.

skills/modern-web-guidance/guides/visual-design/expose-canvas-content-to-browser-features.md

  • Network accessline 429
    # Embed <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>
  • Network accessline 430
    <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>

skills/modern-web-guidance/guides/visual-design/interactive-content-in-3d-scenes.md

  • Network accessline 444
    # Embed <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>
  • Network accessline 445
    <script src="https://cdn.jsdelivr.net/npm/three-html-render/dist/polyfill.js"></script>

skills/modern-web-guidance/guides/webmcp/agentic-javascript-tools.md

  • Network accessline 55
    }, {   signal: controller.signal,   exposedTo: ["https://checkout.example.com"],
  • Network accessline 56
    signal: controller.signal,   exposedTo: ["https://checkout.example.com"], });
  • Network accessline 57
    exposedTo: ["https://checkout.example.com"],
  • Network accessline 132
    async execute(input, { signal }) {   const response = await fetch(`/api/data/${input.id}`, { signal });
  • Network accessline 133
    const response = await fetch(`/api/data/${input.id}`, { signal });
  • Network accessline 173
    * **APIs that accept a signal** (`fetch()`, `addEventListener()`, `ReadableStream` readers): pass `signal` straight through.
  • Network accessline 195
    try {       // Passing `signal` aborts the network request the moment execution is cancelled.       const response = await fetch(url, { priority, signal });
  • Network accessline 196
    // Passing `signal` aborts the network request the moment execution is cancelled.       const response = await fetch(url, { priority, signal });       if (!response.ok) {
  • Network accessline 197
    const response = await fetch(url, { priority, signal });
  • Network accessline 296
    // Query tools registered in the embedded cart frame that exposed them to this checkout origin: const cartTools = await document.modelContext.getTools({   fromOrigins: ["https://cart.example.com"],
  • Network accessline 297
    const cartTools = await document.modelContext.getTools({   fromOrigins: ["https://cart.example.com"], });
  • Network accessline 298
    fromOrigins: ["https://cart.example.com"],

skills/modern-web-guidance/guides/webmcp/webmcp.md

  • Network accessline 43
    * **Required Version**: Chromium `146.0.7672.0` or higher. * **Activation**: Requires enabling the flag `chrome://flags/#enable-webmcp-testing` or `edge://flags/#enable-webmcp-testing`. * **Specification**: Evolving [Draft Community Group s
  • Network accessline 45
    * **Specification**: Evolving [Draft Community Group specification](https://webmachinelearning.github.io/webmcp/); not yet a standards-track recommendation.

How the signals fit together

Facts from a static read of the files at the pinned commit. They describe what the code does, not why.

Some files could not be read; the facts below still hold.

Signal confidence: 485 facts

and 435 more

Works with

Agent compatibility, from the files in this repository
AgentStatusEvidenceInstall to
Claude CodeNativeManifest .claude-plugin/marketplace.json.claude/skills/<skill-name>/
CodexCompatibleStandard SKILL.md skills/chrome-extensions/SKILL.md.agents/skills/<skill-name>/
CursorCompatibleStandard SKILL.md skills/chrome-extensions/SKILL.md.cursor/skills/<skill-name>/
Gemini CLINativeManifest gemini-extension.json.gemini/skills/<skill-name>/
GitHub CopilotCompatibleStandard SKILL.md skills/chrome-extensions/SKILL.md.github/skills/<skill-name>/
OpenCodeCompatibleStandard SKILL.md skills/chrome-extensions/SKILL.md.opencode/skills/<skill-name>/
  • Native The repository ships a manifest, folder or frontmatter field for this agent.
  • Compatible A standard SKILL.md that this agent can read.
  • Unknown No evidence either way.

Derived automatically from paths, manifests and frontmatter. Not tested on each agent.

Explore alternatives and comparisons

Add this badge to your README

It updates every night and links to this page.

GoogleChrome/modern-web-guidance: #455 on hotskills, 2.6k stars

[![GoogleChrome/modern-web-guidance on hotskills](https://hotskills.dev/badge/googlechrome-modern-web-guidance.svg)](https://hotskills.dev/skill/googlechrome-modern-web-guidance/)