I installed Modern Web Guidance in My Projects - Here's What Actually Changed

I ran a controlled refactor on my production Next.js app to see if Chrome's Modern Web Guidance (MWG) actually stops AI from writing outdated, framework-heavy code. Here is what actually changed.


I ran a controlled refactor on my production Next.js app, Parlez Bien, to see if Chrome's Modern Web Guidance (MWG) actually stops AI from writing outdated, framework-heavy code.

This experiment builds on the foundational concepts I broke down in my FreeCodeCamp guide on Modern Web Guidance, but this time, I wanted to move beyond theory and get hard numbers. I installed Chrome’s MWG into my AI agent (via Antigravity CLI) and asked it to refactor my UI components.

I didn’t just want a summary of what changed; I wanted the raw diffs and the exact metrics. Here is exactly what happened when an AI agent stopped writing "React-first" code and started writing "Platform-first" code.


What I Tested and Why

I selected four specific UI components in Parlez Bien that relied on common, slightly hacky React patterns to solve problems the browser can now handle natively:

  1. Toast Notification: Timer-based unmounting state hacks.
  2. Toggle Switch: Custom simulated button-based toggles causing accessibility issues.
  3. VocabChip: Abusing interactive <button> elements for non-interactive state displays.
  4. Waveform Visualizer: Injecting inline stylesheets via dangerouslySetInnerHTML.

The Methodology

First, I asked the AI agent to refactor them using its default training. Then, I installed the Modern Web Guidance skill (agy skill install GoogleChrome/modern-web-guidance), which injects real-time Web Platform Baseline data into the agent's context window, and ran the exact same refactor prompts.

To measure the delta, I applied a strict, consistent scoring rubric to the raw diffs before looking at the totals.


Win #1: Killing the "Exit Animation" React Hack

Result: Eliminated 12 lines of JS, removed 2 hooks, and purged 2 DOM APIs by adopting the native Popover API.

The Concept: Replaced custom React timer-based unmounting state hacks with the native browser popover top-layer API and CSS discrete transitions.

The Pain Point (Before)

In React, if you want a component (like a Toast notification) to fade out before it unmounts from the DOM, you usually have to write a brittle useEffect with a setTimeout. You keep the component in the DOM just long enough for the CSS animation to finish, then you flip a state flag to unmount it.

// ❌ BEFORE: The classic React animation hack
const [shouldRender, setShouldRender] = useState(visible)
useEffect(() => {
  if (visible) {
    setShouldRender(true)
  } else {
    const timer = setTimeout(() => {
      setShouldRender(false)
    }, 200)
    return () => clearTimeout(timer)
  }
}, [visible])

if (!shouldRender) return null
return (
  <div
    className={`... fixed bottom-6 right-6 z-[200] transition-all duration-200`}
  />
)

The MWG Fix (After)

With MWG aware that the native Popover API and CSS @starting-style are now Baseline, the agent completely deleted the useEffect timer. It let the browser's native Top-Layer handle the rendering and stacking context.

// ✅ AFTER: Native Top-Layer handles rendering and stacking
return (
  <div
    ref={popoverRef}
    popover="manual"
    className={`toast-notification fixed bottom-6 right-6 z-[200] ${visible ? 'toast-visible' : ''}`}
  />
)
// (Paired with native @starting-style animations in globals.css)

The Takeaway: MWG knows the browser can handle entry/exit animations natively. It saved us 12 lines of brittle state-management code and eliminated a potential memory leak from uncleared timers.


Win #2: Fixing "Div Soup" Accessibility in Toggles

Result: Removed 4 lines of JS and 1 DOM API, resolving 2 accessibility violations by adopting a native checkbox.

The Concept: Refactored custom simulated button-based toggles to use a standard, accessible <input type="checkbox"> styled natively using Tailwind sibling state selectors (peer).

The Pain Point (Before)

It is incredibly common for AI (and humans) to build toggle switches using a <button> or a <div> with custom onClick handlers. This looks fine visually, but it completely breaks keyboard navigation and screen readers.

// ❌ BEFORE: Accessible label is unlinked; custom button simulates a checkbox
<button
  type="button"
  disabled={disabled}
  onClick={() => !disabled && onChange(!checked)}
  className={`relative h-6 w-10 rounded-full ${checked ? 'bg-[#2563eb]' : 'bg-[#d4cfc2]'}`}
>
  <span
    className={`... absolute ${checked ? 'translate-x-5' : 'translate-x-1'}`}
  />
</button>

The MWG Fix (After)

MWG enforced native form semantics. It refactored the component into a native checkbox hidden with Tailwind's sr-only, using peer-checked to style the visual switch.

// ✅ AFTER: Label HTML-linked via useId; native checkbox handles events
const switchId = useId()
return (
  <>
    <label htmlFor={switchId} className="cursor-pointer">
      {label}
    </label>
    <label className="relative inline-flex shrink-0 cursor-pointer items-center">
      <input
        id={switchId}
        type="checkbox"
        checked={checked}
        onChange={(e) => onChange(e.target.checked)}
        className="peer sr-only"
      />
      <div className="h-6 w-10 rounded-full bg-[#d4cfc2] after:absolute after:transition-transform after:content-[''] peer-checked:bg-[#2563eb] peer-checked:after:translate-x-4" />
    </label>
  </>
)

The Takeaway: It didn't just make it look like a toggle; it made it act like a real form element. We got Spacebar toggling and VoiceOver support for free, without writing a single line of ARIA code.


Win #3: Semantic Tag Resolution for UI Chips

Result: Removed 1 line of JS and resolved 1 accessibility violation by enforcing semantic HTML.

The Concept: Stopped using <button> elements for non-interactive state displays, replacing them with dynamic rendering tags (span / button) based on the presence of an onClick callback.

The Pain Point (Before)

We had a <VocabChip> component that was always rendered as a <button>. If it wasn't clickable, we just passed disabled={true}. Screen readers would annoyingly announce "Vocabulary word, disabled button" to users.

// ❌ BEFORE: Element is always a button, forced disabled if not interactive
return (
  <button
    type={isInteractive ? 'button' : undefined}
    onClick={isInteractive ? onClick : undefined}
    disabled={!isInteractive}
    className={`... inline-flex items-center justify-center`}
  >
    <span>{word}</span>
  </button>
)

The MWG Fix (After)

MWG understands that semantic HTML matters. It implemented dynamic tag resolution, ensuring non-clickable components render as static <span> elements.

// ✅ AFTER: Suffix elements natively swap wrapper tag to <span> if not interactive
const Tag = isInteractive ? 'button' : 'span'
return (
  <Tag
    type={isInteractive ? 'button' : undefined}
    onClick={isInteractive ? onClick : undefined}
    className={`... inline-flex items-center justify-center focus-visible:ring-2`}
  >
    <span>{word}</span>
  </Tag>
)

The Takeaway: MWG stopped the AI from abusing interactive elements for static display, instantly improving the assistive technology experience.


Win #4: Purging dangerouslySetInnerHTML for CSS

Result: Eliminated 7 lines of JS and purged 1 DOM API (dangerouslySetInnerHTML) by migrating to CSS keyframes.

The Concept: Removed inline stylesheet injections via React's dangerouslySetInnerHTML and migrated custom keyframes to the global stylesheet (globals.css).

The Pain Point (Before)

The AI had injected @keyframes directly into the DOM using React's dangerouslySetInnerHTML. In a Next.js environment, this is a massive red flag. It triggers Content Security Policy (CSP) violations and causes severe React hydration mismatches between the server and client.

// ❌ BEFORE: Inject keyframe stylesheets at run-time directly inside the DOM
<style
  dangerouslySetInnerHTML={{
    __html: `
      @keyframes waveform-bounce {
        0%, 100% { height: 20%; }
        50% { height: 100%; }
      }
    `,
  }}
/>

The MWG Fix (After)

MWG recognized that runtime CSS injection is an anti-pattern in modern, secure web apps. It extracted the keyframes and moved them to globals.css.

/* ✅ AFTER: Consolidated inside global styles.css */
@keyframes waveform-bounce {
  0%,
  100% {
    height: 20%;
  }
  50% {
    height: 100%;
  }
}

The Takeaway: It prioritized security and Next.js server/client hydration stability over component-level encapsulation.


Measuring the Delta: The Benchmark

The before/after diffs tell a qualitative story. But real technical research requires numbers someone else can reproduce.

To ensure this wasn't just "AI slop" observation, I applied a consistent, strict scoring rubric across all four components. I counted executable JavaScript lines, React hooks, direct DOM API calls, and accessibility violations resolved from the actual diffs, before looking at the totals.

Here is the raw data:

ComponentJS Lines RemovedHooks RemovedDOM APIs RemovedNative API Adopteda11y Fixed
Toast Notification1222Popover API0
Toggle Switch401Native Checkbox2
VocabChip100Semantic HTML1
Waveform Visualizer701CSS Keyframes0
TOTAL24243

The aggregate: MWG eliminated 24 lines of executable JavaScript, removed 2 React hooks, purged 4 direct DOM/React-DOM API manipulations, and resolved 3 accessibility violations across four components — without a single change to the component's visual output or core behavior.

The methodology and raw JSON scores are published here: mwg-refactor-benchmark GitHub Repo. If you want to run the same counting experiment on your own codebase, the exact rubric is in methodology.md.


The Meta-Analysis: Platform > Framework

Looking at the aggregate data: a 24-line reduction in executable JS, the removal of 2 React hooks, and 3 resolved accessibility violations, a clear pattern emerges. Left to its own devices, an AI coding agent solves problems using Framework Patterns (state, effects, custom components).

When you inject Modern Web Guidance, it forces the agent to pause and ask: "Wait, does the browser do this natively now?"

The benchmark proves this shifts the paradigm from Framework-First to Platform-First. By offloading work to the browser engine (like the Popover API and native checkboxes), we measurably reduced the JavaScript footprint. Furthermore, the data shows it acts as an automated Accessibility Auditor, resolving 3 distinct assistive technology violations that the default AI training completely ignored.


The Friction: Where MWG Over-Corrected

Before I wrap up, I’d be doing you a disservice if I painted this as a flawless magic bullet. Injecting MWG into your agent's context window isn't without friction. Here is where the refactor actually caused me headaches:

1. The Encapsulation Trade-off

In Win #4, moving keyframes to globals.css solved the CSP and hydration issues, but it broke my component-level CSS encapsulation. If I delete the WaveformVisualizer component later, I now have orphaned CSS sitting in my global file. MWG gave me the right architectural direction for security, but I still had to act as the senior dev to manually namespace the classes to prevent style leaking.

2. The "Bleeding Edge" Cliff

In Win #1, the agent used CSS @starting-style and transition-behavior: allow-discrete. These are incredibly powerful, but they are new. While they are technically Baseline, they are highly obscure to a junior developer who is used to standard transition: opacity. MWG assumes you want the absolute newest Web Platform features, which sometimes means trading "familiar React patterns" for "cutting-edge CSS that requires Googling."


The Verdict

Asking an AI agent to refactor with Modern Web Guidance is a highly effective way to pay down technical debt, eliminate legacy hacks, and accidentally fix accessibility issues.

However, it is not a "set it and forget it" solution. You must still act as the senior reviewer. You need to verify that the agent's definition of "modern" aligns with your product's actual browser support requirements, and you need to manage the architectural trade-offs (like CSS encapsulation) that the agent doesn't fully grasp.

Ultimately, MWG turns your AI coding agent from a junior developer who blindly copies 2019 StackOverflow answers into a mid-level engineer that actually reads the MDN docs.