Published: November 10, 2026
MetaMask is a self-custodial financial platform with more than 100 million downloads across approximately 190 countries. Its browser extension is developed in the open, so a steady stream of pull requests comes from contributors inside and outside the company.
MetaMask UX engineer Francis Nepomuceno reviewed many of those pull requests and wanted a consistent way to help contributors apply accessibility best practices and use modern web features. In his editor, he already used Chrome's Modern Web Guidance, a set of skills that brings web platform best practices and browser compatibility data to coding agents. To bring the same guidance to other contributors, he set up a bot to review every pull request to MetaMask's open-source repository, regardless of the tools its author used.
The challenge: Keeping up with modern web features
Modern HTML and CSS keep adding features that improve accessibility and user experience, and tracking which ones work across browsers is hard. With many contributors, that knowledge has to reach everyone who opens a pull request.
Security adds another reason to care: MetaMask sandboxes every third-party dependency by default, which makes a native browser feature cheaper to adopt than a library alternative. As Nepomuceno put it, "having access to these modern APIs, like being able to use dialogs and dropdowns without JavaScript, was a big win."
The solution: Modern Web Guidance reviews every pull request
On September 16, 2026, a pull
request to
MetaMask/metamask-extension
added
a "How it works" page with an FAQ built the way most React FAQs are built:
// Before: Custom React state (removes content from DOM)
const [expanded, setExpanded] = useState(false);
<button type="button" aria-expanded={expanded} onClick={() => setExpanded(c => !c)}>
<Text>{question}</Text>
</button>
{expanded ? <Text>{answer}</Text> : null}
About five minutes later, the bot commented. Citing the
search-hidden-content
guide, it made three points:
- Rendering each answer conditionally removes it from the DOM, so collapsed text can't be found with the browser's find-in-page and is harder for assistive technology to discover.
- A native
<details>/<summary>disclosure (Baseline since 2020) keeps the content in the DOM with the right semantics. For mutually exclusive panels, a sharednameattribute (Baseline Newly available since 2024) closes the others automatically; for a multi-open FAQ, omit it. - If the team preferred its existing Disclosure
component, it should at least keep answers in the DOM with
hidden="until-found"and abeforematchlistener that syncsaria-expandedand the icon state.
// After: Native <details> / <summary> disclosure (findable with find-in-page)
<details>
<summary>
<Text>{question}</Text>
</summary>
<Text>{answer}</Text>
</details>
Thirteen minutes later, the author pushed a
fix. The component
became a native <details>/<summary> disclosure, collapsed answers stayed in
the DOM for find-in-page, and two navigation buttons became links.
That bot is a Cursor Automation running Modern Web Guidance, and Nepomuceno set it up with a three-line prompt. By October 21, 2026, five weeks in:
- The bot had run on roughly 480 pull requests and commented on 64 of them (57 feature and fix pull requests, plus 7 automated release and sync pull requests) from 26 authors.
- On the feature and fix pull requests, engineers fixed 43 of its findings, and partly fixed 3 more, across 22 pull requests.
- Engineers acted quickly: of the 38 fixes with an identifiable commit, 19 landed within 15 minutes and 26 within an hour, for a median of 15.2 minutes from comment to fix.
Here's how MetaMask configured the bot, what it caught, and where it was noisy.
The setup is a three-line prompt
Asked how the automation is configured, Nepomuceno answered: "Sure, there's really nothing special in our setup. We just keep it concise and scoped." The entire instruction:
- Run /modern-web-guidance for any client-facing changes
- Run /chrome-extensions for any relevant extension changes
- Comment on the PR only when there are issues to address. Keep the comment focused on actionable items
How that behaves in practice:
- It's advisory: On its first two days the bot posted "request changes" reviews (and one approval), which authors dismissed once they had addressed them; since September 18 every review has been a comment. It does not block a merge, so authors keep the final call on each suggestion.
- It cites specific guides and files in the repository: Across the 64 pull
requests it commented on, the bot raised 122 findings. Of the 102 on feature
and fix pull requests, 63 name the specific Modern Web Guidance guide they
are applying, such as
search-hidden-content,state-aware-sticky-headers, orsms-otp-form, and point to an existing file in the repository when it already uses the recommended pattern. - It stays quiet unless a pull request touches the UI: Of the roughly 480 pull requests in those five weeks, at least 100 touched UI or client code, and the bot averaged about two findings per pull request it commented on. Teams with mostly frontend repositories can expect it to comment on a larger share.
The prompt itself works with any agent runner; Modern Web Guidance installs as a skill or plugin for Cursor, Claude Code, Codex, GitHub Copilot, Antigravity, and other coding agents. When an agent runs the skill, it looks up the matching guides in a local index with no API keys required, and checks the diff against them, using whichever model the team's agent runner already provides.
What Modern Web Guidance caught that linters don't
A static linter can flag a missing attribute on a single element, but the findings that follow came down to interaction behavior, HTML semantics, and how components fit together across files.
A transaction fee field that looked editable while silently ignoring input
In MetaMask's advanced transaction fee settings, the gas limit field (which caps the network fee a transaction can consume) looked editable but silently ignored users' input. This happened when a fee estimate was still loading or had failed. Meanwhile, the Save button was disabled, with no explanation that assistive technology could read.
Citing the forms guide, the bot flagged three fixes:
- Disable the gas limit field when no estimate is available, and connect its visible status text to the field so that assistive technology reads the explanation.
- Connect the disabled Save button to that same status text so that screen readers know why it's disabled.
- Switch the field to a numeric input mode so mobile users get a numeric keypad.
The author applied all three fixes across both settings modals and consolidated them into a single component.
Banner buttons that hid their URLs
In a status banner for one of MetaMask's trading features, the inline "FAQ" and "contact MetaMask Support" actions were built as buttons that opened a new tab with JavaScript rather than as links. Within three minutes, the bot—citing the HTML and accessibility guides—flagged that screen readers announce them as buttons and that users lose link affordances such as copying the URL or opening it in a new tab from the context menu. It also pointed to an existing banner component in MetaMask's codebase that already renders these actions as real links.
Twelve minutes later, the author switched both actions to links. "I find it very useful that once a guidance has been adopted, future reviews mention that as a reference example," Nepomuceno said.
Verification inputs whose labels lived somewhere else
The bot's ability to read across files also paid off on a multi-step form. A static linter only sees a text field with placeholder text inside each step and can't tell that the visible heading and instructions live in a parent layout component. Citing the forms and accessibility guides, the bot caught that the placeholder was the field's only label, that the step title and instructions in the parent layout weren't associated with the input, and that error and "code resent" messages weren't announced to screen readers. Fifteen minutes later, all three were fixed, and that accessibility wiring stayed intact when a follow-up pull request restyled the code input as six visual digit boxes.
A few more things the bot caught
Five more findings from the same five-week run:
- A CSS detail the engineer behind the bot missed: Nepomuceno's own pull request for sticky home tabs nested CSS scroll-state queries without naming their containers and toggled a border in a way that shifted layout mid-scroll. The bot cited the state-aware sticky headers guide, and he fixed both. He found the reviews helpful for anchor positioning and scroll-state queries.
- Slippage capped mid-keystroke: Custom slippage inputs (the price movement a user will tolerate on a trade) clamped values over 100% on every keystroke, turning 101 into 100 while the user was still typing. Following the forms guide, the fix moved validation to when the field loses focus and added a visible warning banner.
- A loading indicator that screen readers couldn't use: A token-list loading skeleton put its "loading" label on a generic element with no role, which ARIA prohibits. The bot pointed to two components in the codebase that already used MetaMask's screen-reader-only pattern (both updated after a Modern Web Guidance review six days earlier), and the author aligned the skeleton with that pattern eight minutes later.
- Unguarded async action: An asynchronous "View on provider" button had no in-flight guard, so a double-click could open duplicate tabs and background watchers. The author added a guard less than four minutes after the comment.
- Keystroke validation without a form: An Import NFT page validated on
every keystroke and lacked a
<form>element for submit semantics. Both were fixed 19 minutes after review.
Every review is public. The bot's full comments are on each linked pull request, and you can browse all of them on GitHub.
What it didn't fix, and how noisy it is
Not every finding landed. The following table shows how MetaMask tallied the 102 findings on feature and fix pull requests (20 more landed on 7 release and sync pull requests, where a review isn't expected to change code):
Broken down by theme across all 122 findings (including the 20 on release and sync pull requests):
A few patterns in those numbers:
- Fixes that stay inside one component land much more often than cross-cutting accessibility changes. Forms and HTML fixes stay inside the component under review, so authors usually apply them right away (19 of 31 fixed). Accessibility had the most findings (38) but only 12 were fixed, usually because the fix was outside the pull request's scope or needed a shared design-system component that didn't exist yet.
- "Other" is where it wanders outside web-platform guidance. Sixteen findings covered design-system consistency, logic bugs, copy, test quality, dark mode, and code hygiene; 3 were acted on, one of them a real regression (a network list change that broke form prefill). Most of those 16 were easy to pass over, but catching that regression made them worth a quick look.
- False positives came from how the agent applied the guides, and most of the noise is fixable in the setup. Because the review bot is an agent reading a diff rather than a static linter, its false positives came from misreading surrounding code or applying a rule more strictly than the linked guide does. Skipping release and sync branches and tightening the prompt so the agent sticks to rules explicitly stated in a guide are the obvious next adjustments.
Nepomuceno describes the broader effect on the team and review turnaround:
"The reviews are really helpful. They've helped surface and get our engineers familiar with modern APIs like interest invokers and the Popover API."
"It hasn't increased PR review times, if anything it likely reduced them. Many engineers use agents to address the feedback. The issues Modern Web Guidance caught would have otherwise required a human reviewer familiar with these modern web techniques."
MetaMask engineer David Murdoch has also contributed back to the guidance itself: When the CSS layout guide had an error in one of its examples, he filed an issue, and the Modern Web Guidance team merged a correction two days later.
What MetaMask would tell a team considering it
- Read the guidance before writing anything. Run
npx modern-web-guidance@latest search "accordion find in page"to see which guides an agent would retrieve for a task. You can also browse the full set of Modern Web Guidance guides. - Start with the three-line prompt and the agent you already run. Install
the skill (
npx modern-web-guidance@latest install, or an agent's plugin command), point whatever can run on pull requests at it, and tell it to comment only when there is something actionable and to stick to rules explicitly stated in a guide. Keeping the bot quiet when nothing is wrong is why MetaMask's engineers still read its comments. - Expect some findings to go unaddressed. Of 102 findings on feature and fix pull requests, 43 were fixed and 36 were declined or not addressed. That ratio works well for an advisory review bot, whereas it would be disruptive as a blocking check.
- Keep humans reviewing. The bot is good at web-platform semantics, modern CSS, and interaction patterns, but it does not know the product.
There is also what MetaMask hasn't measured yet: five weeks in, the team hasn't tracked per-pull-request cost, runtime, model comparisons, or how the review bot behaves outside a React codebase.
With three lines of configuration, MetaMask got a review bot that cites a specific guide for most findings (and an existing in-repo example when one exists). Its accepted suggestions are usually fixed within the hour.