Modern Web Guidance 101

1. What is Modern Web Guidance?

Modern Web Guidance applies modern best practices and browser compatibility directly to your coding agents. These skills ensure your code remains aligned with current web platform capabilities. From developing new prototypes to refactoring legacy systems, Modern Web Guidance provides access to modern web standards.

Developers can use it to:

  • Build on a solid foundation: Start projects that use interoperable web features.
  • Modernize legacy code: Replace bespoke implementations of common user interface patterns.
  • Learn as you develop: Improve your knowledge of modern web patterns as the skill provides context-aware guidance during development.

By auditing a legacy app, setting a Baseline target, and contrasting standard AI suggestions against Modern Web Guidance rules, you learn to prompt modern-web-guidance enhanced coding agents to generate high-performance, modern web code instead of relying on outdated or generic model outputs.

2. Prerequisites

Before you start this codelab, ensure that you have the following knowledge:

The codelab uses the following:

This codelab starts with a Legacy "Cozy Nook" app that is intentionally composed of legacy code. Clone the demo repository and go to the cozy-nook-bookshop web app.

git clone git@github.com:GoogleChromeLabs/modern-web-guidance-demos.git
cd modern-web-guidance-demos/legacy-demos/cozy-nook-bookshop/

3. Set your Baseline target

Baseline provides information on which features are interoperable in browsers today. It also offers a way to express which browsers you want to support, without requiring you to specify browser engines and versions. A feature is considered Baseline if it is interoperable.

Before you develop your web application, choose your Baseline target. By default, modern-web-guidance uses Baseline Widely available, which includes features that have been interoperable for at least 30 months. If you need to support newer features, you'll need to include the appropriate Baseline target in your AGENTS.md file.

For this codelab, this project uses a fixed target of baseline widely available on 2026-06-01.

// AGENTS.md
This project's Baseline target is "Baseline widely available on 2026-06-01".

4. Identify project priorities

After you choose your Baseline target, define the priorities and batch related features and topics. Adopt the mental model of incremental improvement, as you would when you build a feature.

Categorize your updates based on specific outdated features or broader web development disciplines, for example:

  • Performance: Optimize your Core Web Vitals.
  • User experience: Improve interactions and usability.
  • Accessibility: Address accessibility issues to broaden access to your application.
  • Forms and security: Modernize input handling and harden your application's data entry points.

In this codelab, you focus on comparing the performance of the legacy bookshop app to see how the Modern Web Guidance skill improves its speed. Focus on one task at a time to monitor the changes the agent performs and ensure the result aligns with your project goals.

To begin, get a clear picture of how the bookshop app performs in its initial state using a Lighthouse audit.

Open Antigravity CLI on your local machine and start a new session:

agy

You should see agent output similar to the following.

 Bash(ctrl+o to expand)
 Thought for 13s
 This report will detail the desktop and mobile scores, provide a comparative metrics table, explain the root causes of the performance bottlenecks, and offer highly actionable recommendations based on modern web standards (e.g. Baseline Widely available on 2026-06-01 target).


 Create(lighthouse_audit_report.md) (ctrl+o to expand)
 Thought for 5s
  Confirming Task Completion
  I have successfully run the Lighthouse audits using  npx lighthouse  for both desktop and mobile viewports against a production build of the application.


The generated local reports have been saved in the project root:
 Mobile Reports: lighthouse-mobile.report.html and lighthouse-mobile.report.json
 Desktop Reports: lighthouse-desktop.report.html and lighthouse-desktop.report.json

I have compiled the audit scores, identified performance bottlenecks, and outlined a step-by-step key improvement action plan in the following artifact:

Open lighthouse_audit_report.md

Opening the Markdown, we get around the following results:

Here is the complete Lighthouse audit report generated for the application:

**Lighthouse Audit Report: Cozy Nook Bookshop**

This report provides the Lighthouse audit scores, core web vitals performance
metrics, and key areas for improvement for The Legacy Cozy Nook in development mode.

**Summary Scores**

| Category        | Mobile Score | Desktop Score |
|-----------------|--------------|---------------|
| Performance     | 61 / 100    | 93 / 100 |
| Accessibility   | 98 / 100  | 98 / 100 |
| Best Practices   | 96 / 100  | 96 / 100 |
| SEO       | 92 / 100  | 92 / 100 |

** Core Web Vitals & Key Metrics**

| Metric        | Mobile Value | Desktop Value |
|-----------------|--------------|---------------|
| First Contentful Paint (FCP)     | 2.9 s    | 0.7 s |
| Largest Contentful Paint (LCP)   | 4.8 s  | 1.2 s |
| Total Blocking Time (TBT)  | 0 ms | 0 ms |
| Cumulative Layout Shift (CLS)      | 0.336  | 0.114 |
| Speed Index (SI)      | 2.9 s  | 0.7 s |

The app scores 61/100 for performance on mobile. Query modern-web-guidance for recommendations to optimize the app for mobile and improve the performance score.

5. Query to improve performance

To evaluate the differences between recommendations generated by the standard base model and those produced when modern-web-guidance is active, perform a comparison test while you ask the agent for performance optimization suggestions.

First, without installing modern-web-guidance, query the base model to see what sort of mobile web performance enhancements it can recommend.

Once you see an output of web features with reasons for why the model recommended it, go ahead and install modern-web-guidance in another terminal window and accept all the defaults.

npx modern-web-guidance@latest install

Back to Antigravity, query the newly installed skill, and ask it to compare itself with the list that was recommended by the base model.

 Bash(npx -y modern-web-guidance@latest search "performance")
    [{"id":"performance","description":"Actionable guidelines for optimizing modern web applications. Use this guide when auditing performance, optimizing loading metrics, fixing slow interactions and optimizing Core Web Vitals (LCP, INP, CLS)","category":"performance","similarity":0.5569},
            {"id":"efficient-background-processing","description":"Conserve system resources and battery life by pausing background JavaScript execution (such as `<canvas>` animations, WebGL rendering, or high-frequency WebSocket data polling) when the component is off-screen and then resume them just-in-time when they scroll back into view.","category":"performance","featuresUsed":["content-visibility"], "similarity":0.5066},
            {"id":"html","description":"Action-oriented guidelines for modern HTML architecture, semantics, native interactive APIs (Dialog, Popover, Details), focus management, and resource prioritization. Use this
            guide when structuring web documents, implementing native overlays, or optimizing resource loading order.","category":"html", "similarity":0.4478},
            {"id":"faster-spa-view-transitions","description":"Enable faster transitions back to previously visited views in a Single-Page Application (SPA) by preserving their structural DOM state instead of
            destroying and rebuilding them on every navigation.","category":"performance","featuresUsed":["content-visibility"], "similarity":0.444},
            {"id":"identify-heavy-scripts","description":"Identify the scripts most responsible for long animation frames","category":"performance","featuresUsed":["Long animation
            frames"], "similarity":0.4287}] (ctrl+o to collapse)


 Bash(npx -y modern-web-guidance@latest search "image")
    [{"id":"deliver-optimized-decorative-images","description":"Deliver optimized decorative images (such as backgrounds, UI icons, or complex masks) by simultaneously providing next-generation image formats
            (like AVIF or WebP) alongside multiple pixel densities (like 1x and 2x) so the browser can dynamically negotiate the best combination of file size and visual quality for the user's device
            capabilities.","category":"user-experience","featuresUsed":["image-set()"], "similarity":0.4038},
            {"id":"performance","description":"Actionable guidelines for optimizing modern web applications. Use this guide when auditing performance, optimizing loading metrics, fixing slow interactions and
            optimizing Core Web Vitals (LCP, INP, CLS)","category":"performance", "similarity":0.3761},
            {"id":"visually-texture-content","description":"Apply realistic weathering and texture patterns to elements to give them an organic, aged, or physical material
            appearance.","category":"user-experience","featuresUsed":["Masks"], "similarity":0.3716},
            {"id":"resolution-optimized-pseudo-elements","description":"Use resolution-optimized images in CSS pseudo-elements (such as `::before` and `::after`) to reduce the number of DOM
            nodes.","category":"performance","featuresUsed":["image-set()"], "similarity":0.3566},
            {"id":"optimize-image-priority","description":"Optimize the loading priority of Largest Contentful Paint (LCP) candidate images and deprioritize non-critical images to reduce critical resource load
            delays.","category":"performance","featuresUsed":["Fetch priority"],"similarity":0.32}] (ctrl+o to collapse)

 Bash(npx -y modern-web-guidance@latest retrieve "performance,optimize-image-priority")
    <output +165 lines>
            - **RECOMMENDED**: Avoid using `fetchpriority="auto"`. If you want the default priority, omit the attribute entirely to keep your HTML clean.
            - **DO NOT** combine `fetchpriority="high"` with `loading="lazy"` for the LCP image.
            - **DO NOT** use the deprecated `importance` attribute. It has been replaced by `fetchpriority` and is not supported by any browser.
            ## Fallback strategy
            Baseline status for Fetch priority: Newly available. It's been Baseline since 2024-10-29.
            Supported by: Chrome 103 (Jun 2022), Edge 103 (Jun 2022), Firefox 132 (Oct 2024), and Safari 17.2 (Dec 2023).
            The `fetchpriority` attribute is a progressive enhancement for the `<img>` element. If a browser does not support it, the attribute is ignored, and the browser uses its default priority heuristics. (ctrl+o
     to collapse)  

After the agent finishes its reasoning, it presents a comparative analysis that shows the model's recommendations with and without the modern-web-guidance skill and highlights overlapping suggestions. The following output depends on the Gemini model version and the current modern-web-guidance version.

Because local environments may differ, share your specific outcomes and feedback regarding Modern Web Guidance by opening an issue in the GitHub repository.

The agent's output should be similar to the following:

 ### 1. Base Model Knowledge Recommendations (Internal Training Only)
  Based purely on standard web development practices, the following steps are recommended to improve the application's mobile performance score:

  • Hero Image Optimization: Move the dynamic Javascript-loaded hero image into the source HTML file ( index.html ) so the browser preload scanner can fetch it immediately. Add  fetchpriority="high"  and serve the image in modern WebP
  or AVIF formats.

  • Layout Stability (CLS): Provide explicit  width  and  height  dimensions in HTML image elements so the browser can calculate the layout box size before the image has finished loading.
  • Payload Compression: Minify JS and CSS bundles and compress images to reduce the 6.1 MB payload.
  • Resource Optimization: Defer non-critical scripts and lazy-load offscreen/below-the-fold images.


  ──────


  ### 2. Fetched Modern Web Guidance Guides
  The following official performance guides were successfully fetched and inspected from the repository's local skills folder:

  1.  optimize-image-priority.md
  2.  improve-next-page-load-performance.md
  3.  performance.md
  ──────

  ### 3. Comparison & Key Constraints Comparison
  Below is the side-by-side comparison of the base model recommendations against the fetched performance guidelines:

    | Optimization Area | Base Model Recommendation | Modern Web Guidance Rule | Mandatory Constraints & Discrepancies |
|---|---|---|---|
| Lazy Loading & Fetch Priority Interaction | Standard separation of lazy-load and high priority. | MANDATORY: Do not combine fetchpriority="high" with loading="lazy" on LCP images, and do not use fetchpriority="low" on standard below-the-fold lazy-loaded images. | Constraint: Below-the-fold lazy-loaded images must load at normal priority when they enter the viewport; low priority is reserved strictly for hidden above-the-fold content. |
| Speculative Loading | Preload the next page elements or assets generally. | DO: Use the Speculation Rules API (JSON-based script) to prefetch or prerender pages the user will likely visit next. | Discrepancy: The base model recommends traditional asset preloads. The guide introduces modern speculation rules (list and document rules). |
| Speculative Loading Restrictions | Standard speculative prefetching. | DO NOT use speculation rules on Single Page Applications (SPAs). DO NOT speculate URLs that trigger state changes (e.g., /logout , /add-to-cart ). | Constraint: Explicitly blocks speculation rules for SPA routers and state-changing actions to prevent unintentional sessions/actions from being triggered by background browser requests. |
| Main Thread & INP | Break up long tasks and throttle events. | DO: Implement the 50ms rule: any script execution > 50ms must yield to the main thread. Use scheduler.yield() with a Promise fallback. | Constraint: Explicitly forbids relying only on setTimeout(..., 0) because it places continuations at the back of the queue, potentially starving user input. |
| CSS Content Visibility | Standard style minification. | DO: Pair content-visibility: auto with contain-intrinsic-size for offscreen elements on large, complex pages only. | Constraint: Forbids using content-visibility: auto on simple/small pages or above-the-fold content due to overhead and jumping risks. |

See the following table for a closer look at the comparison:

Optimization area

Base model recommendation

Modern Web Guidance rule

Mandatory constraints and discrepancies

Lazy loading and fetch priority interaction

Standard separation of lazy-load and high priority.

Mandatory: Don't combine fetchpriority="high" with loading="lazy" on LCP images, and don't use fetchpriority="low" on standard below-the-fold lazy-loaded images.

Constraint: Below-the-fold lazy-loaded images must load at normal priority when they enter the viewport; low priority is reserved strictly for hidden above-the-fold content.

Speculative loading

Preload the next page elements or assets generally.

Do: Use the Speculation Rules API (JSON-based script) to prefetch or prerender pages that you will likely visit next.

Discrepancy: The base model recommends basic asset preloads. The guide introduces modern speculation rules (list and document rules).

Speculative loading restrictions

Standard speculative prefetching.

Don't use speculation rules on single-page applications (SPAs). Don't speculate URLs that trigger state changes (for example, /logout or /add-to-cart).

Constraint: Explicitly blocks speculation rules for SPA routers and state-changing actions to prevent unintentional sessions or actions from being triggered by background browser requests.

Main thread and INP

Break up long tasks and throttle events.

Do: Implement the 50ms rule: any script execution longer than 50ms must yield to the main thread. Use scheduler.yield() with a Promise fallback.

Constraint: Explicitly forbids relying only on setTimeout(..., 0) because it places continuations at the back of the queue, potentially starving user input.

CSS content visibility

Standard style minification.

Do: Pair content-visibility: auto with contain-intrinsic-size for offscreen elements on large, complex pages only.

Constraint: Forbids using content-visibility: auto on simpler pages or above-the-fold content due to overhead and jumping risks.

The table shows that the base model understands how to boost performance, but modern-web-guidance refines those broad recommendations into strict rules.

In the section "Lazy loading & fetch priority interaction," the base model recognizes that loading="lazy" is a good practice, but the skill provides crucial information: never combine fetchpriority="low" with a loading="lazy" attribute. This enforcement is useful when you code with AI agents.

After the agent understands the strict modern-web-guidance rules, ask the agent to draft the code for both approaches to see the difference in implementation.

Review the plans that the agent recommends:

 Thought for 2s
  Formulating Mobile Optimization Plans

  Okay, I'm currently focused on crafting two mobile optimization plans as
  requested. I'm structuring them specifically for both a base model and one
  leveraging modern-web-guidance. I'm adding sources and baselines to each for
  comparison. My goal is to present these plans to you for review before any
  implementation begins. I'm trying to make sure I get this exactly right.
...
 ListDir(modern-web-guidance-demos/legacy-demos/cozy-nook-bookshop/static/assets)
    8 files, 0 directories (ctrl+o to collapse)
  Below are two implementation plans to optimize the mobile performance of The
  Cozy Nook to a 90+ score.
  ──────
  ### Plan A: Base Model Only (Traditional Web Performance)

  This plan uses classic web performance optimization patterns based on general
  knowledge from standard MDN/web.dev documentation.

  #### Proposed Changes
  1.  LCP Hero Image HTML Declaration:
       Modify index.html to include the static hero image source directly:
        <img src="./assets/hero-img.png" alt="Old Books stack on wooden table" class="hero-img">
       Remove the dynamic JS source injection in hero.js to prevent JS execution delay blocking the render.
  2.  Critical Preload Link:
       Add a preload link in the <head> of index.html to prioritize the asset request:
        <link rel="preload" as="image" href="./assets/hero-img.png">
  3.  Cumulative Layout Shift (CLS) Fixes:
       Add explicit width and height dimensions to all static image elements in index.html (e.g., hero, staff picks, avatars).

  #### Sources & References
   Preloading Assets: MDN Web Docs - Preloading Content https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preload
   CLS Prevention: web.dev - Optimize Cumulative Layout Shift https://web.dev/articles/cls
### Plan B: Modern Web Guidance (Recommended)

  This plan strictly follows Google Chrome's modern guidelines, progressive
  enhancements, and rules. It minimizes resource contention and leverages native
  speculation tools.

  #### Proposed Changes

  1.  HTML Declaration with Native Fetch Priority:
      • Modify index.html to load the hero image inline and declare priority:
        <img src="./assets/hero-img.png" fetchpriority="high" alt="Old Books stack on wooden table" class="hero-img">

      • Constraint Met: Do not add a duplicate <link rel="preload">. Modern web
        guidance mandates letting the browser's preload scanner natively discover
        the raw HTML image tag. Adding a separate preload resource block causes
        unnecessary network overhead.
       Remove the dynamic source loading in hero.js.
  2.  Explicit Layout Boundaries (CLS):
       Set physical width and height attributes matching the design aspect
        ratio directly on the hero, pick covers, and avatar elements inside
        index.html.
  3.  Speculative MPA Navigation (Next-page optimization):
       Since this is a Multi-Page Application (MPA), embed a Speculation Rules
        script block in the bottom of index.html to prefetch same-origin routes
        (about.html, contact.html, details.html) with moderate eagerness with
        script type "speculationrules" with the following content.
          {
            "prefetch": [{
              "where": {
                "and": [
                  { "href_matches": "/*" },
                  { "not": { "href_matches": "/basket.html" } }
                ]
              },
              "eagerness": "moderate"
            }]
          }

       Constraint Met: We explicitly exclude shopping checkout items like
        basket.html from prefetching to avoid unnecessary/accidental request
        triggers.

  #### Sources & References

   optimize-image-priority.md
   improve-next-page-load-performance.md
   performance.md

6. Compare unguided versus guided implementations

The following are sample agent outputs from comparison testing with Gemini and modern-web-guidance for this bookshop app.

Your results might look different, so use this strategy rather than rigid steps. Use these plans to see how things change when you turn on modern-web-guidance for the bookshop app on your computer. After you've finished running your own comparison tests, ask your agent which approach works best for your specific setup.

You can track your app's performance with Lighthouse or DevTools for Agents to see real-world improvements as you make updates.

1. Lazy loading & fetch priority interaction

Optimize offscreen images to avoid main thread bandwidth contention.

Plan A (base model)

Apply standard loading="lazy" to all offscreen images. (Suboptimal: Lazy-load offscreen assets, but let visible non-LCP above-the-fold assets compete with the LCP image.)

<img src="https://..." alt="..." class="pick-small-img" loading="lazy">

Plan B (Modern Web Guidance)

Target initially invisible above-the-fold elements with fetchpriority="low", and ensure standard lazy-loaded images remain at default priorities. (Best option: Demote hidden assets that block the critical rendering path without diluting scroll-in load times.)

<img src="https://..." fetchpriority="low" width="96" height="144" alt="..." class="pick-small-img" loading="lazy">

2. Speculative loading

Speed up future page loading by prefetching next-page documents or assets.

Plan A (base model)

This approach uses link rel="prefetch" elements. (Suboptimal: Subpage transitions still have an approximately 1-second delay.)

<link rel="prefetch" href="about.html">
<link rel="prefetch" href="contact.html">

Plan B (Modern Web Guidance)

Uses The Speculation Rules API. (Best option: Speculation Rules let you perform prefetching and prerendering with matching queries to lower perceived navigation time.)

<script type="speculationrules">
  {
    "prefetch": [{
      "where": { "href_matches": "/*" },
      "eagerness": "moderate"
    }]
  }
</script>

3. Speculative loading restrictions

Prevent security, performance, or state conflicts by explicitly blocking certain pages from being prefetched, for example, /logout or /basket.html.

Plan A (base model)

This approach requires developers to manually manage which URLs to include. (Suboptimal: This approach is risky because it creates a higher security risk of unintentional background actions.)

Plan B (Modern Web Guidance)

This approach excludes administrative, stateful, or shopping paths declaratively. (Best option: Programmatic exclusions prevent the browser from executing unintended background actions.)

<script type="speculationrules">
  {
    "prefetch": [{
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/wp-admin/*" } },
          { "not": { "href_matches": "/basket.html" } },
          { "not": { "selector_matches": ".do-not-prerender" } }
        ]
      },
      "eagerness": "moderate"
    }]
  }
</script>

4. Main thread and Interaction to Next Paint (INP)

Prioritize main thread availability for user input to maintain high responsiveness.

Plan A (base model):

Defer heavy computations using synchronous callback loops. (Suboptimal: You might experience a high Interaction to Next Paint (INP) if the page has a busy main thread.)

function renderBigCatalog(items) {
  items.forEach(item => {
    renderItem(item);
  });
}

Plan B (Modern Web Guidance):

To keep the main thread responsive, use scheduler.yield() to yield to the main thread. (Best option: The scheduler.yield() method helps keep inputs responsive without task starvation.)

async function yieldToMain() {
  if ('scheduler' in window && 'yield' in scheduler) {
    return await scheduler.yield();
  }

  return new Promise(resolve => setTimeout(resolve, 0));
}

async function renderBigCatalog(items) {
  for (let i = 0; i < items.length; i++) {
    renderItem(items[i]);

    if (i % 50 === 0) {
      await yieldToMain();
    }
  }
}

5. CSS content-visibility

Manage offscreen layout calculations by postponing rendering operations of offscreen elements.

Plan A (base model)

Minify stylesheet bundles. (Suboptimal: Standard rendering overhead on initial paint.)

.book-item {
  display: flex;
  margin: 1rem;
}

Plan B (Modern Web Guidance)

Skip painting offscreen elements until they approach the viewport boundary. (Best option: Prevents mobile rendering overhead on large pages. The modern-web-guidance tool ensures content-visibility is applied only to offscreen elements and pairs it with contain-intrinsic-size. Without this context, a base model might apply it globally, which can cause significant layout shifts during scrolling.)

.book-item {
  display: flex;
  margin: 1rem;
  content-visibility: auto;
  contain-intrinsic-size: auto 350px;
}

7. Implement and verify

After you analyze the differences and identify Plan B as the optimized approach, you can apply it to the project. You can now see how these Modern Web Guidance rules affect your real-world Lighthouse score.

The agent applies the built-in fetchpriority, sets up the Speculation Rules API, and adds microtask yielding. When the final Lighthouse report is generated, the mobile score increases from the initial 61 out of 100.

You've officially modernized the legacy code.

8. Iterate against priorities

This approach evaluates your application when you apply modern-web-guidance and assess how it follows modern web development best practices. As you move forward, experiment with different configurations:

  • Add a new feature: Recommend a floating header that hides while scrolling to maximize screen space.
  • Experiment with different Baseline targets: Shift the Baseline status in the project to observe the effects.
  • Focus on specific disciplines: Observe how different choices affect your codebase.

Iteration helps you navigate the complexities of large or legacy applications; refine, test, build, and repeat.

9. Next steps

For more information about using Modern Web Guidance, see the Modern Web Guidance commands documentation and DevTools for Agents.

If you have questions or feedback for Modern Web Guidance, file an issue in the GitHub repository.