Hoe een Modern Web Guidance-beoordelingsbot MetaMask helpt een toegankelijke, moderne UI te leveren

Gepubliceerd: 10 november 2026

MetaMask is een financieel platform met zelfbeheer met meer dan 100 miljoen downloads in ongeveer 190 landen. De browserextensie wordt openbaar ontwikkeld, dus er komt een gestage stroom pull-verzoeken binnen van bijdragers binnen en buiten het bedrijf.

UX-technicus Francis Nepomuceno van MetaMask beoordeelde veel van die pull-verzoeken en wilde een consistente manier om bijdragers te helpen best practices voor toegankelijkheid toe te passen en moderne webfuncties te gebruiken. In zijn editor gebruikte hij al de Modern Web Guidance van Chrome, een reeks vaardigheden die best practices voor webplatforms en gegevens over browsercompatibiliteit naar programmeeragents brengt. Om dezelfde richtlijnen aan andere bijdragers te geven, heeft hij een bot ingesteld om elk pull-verzoek naar de open-source repository van MetaMask te beoordelen, ongeacht de tools die de auteur gebruikte.

De uitdaging: bijblijven met moderne webfuncties

Moderne HTML en CSS blijven functies toevoegen die de toegankelijkheid en gebruikerservaring verbeteren. Het is moeilijk om bij te houden welke functies in verschillende browsers werken. Met veel bijdragers moet die kennis iedereen bereiken die een pull-verzoek opent.

Beveiliging is nog een reden om hier aandacht aan te besteden: MetaMask plaatst elke afhankelijkheid van derden standaard in een sandbox, waardoor een systeemeigen browserfunctie goedkoper is om te gebruiken dan een bibliotheekalternatief. Nepomuceno zegt hierover: "Het was een groot voordeel dat we toegang hadden tot deze moderne API's, zoals de mogelijkheid om dialoogvensters en dropdownmenu's te gebruiken zonder JavaScript."

De oplossing: Modern Web Guidance beoordeelt elk pull-verzoek

Op 16 september 2026 werd er een pull-verzoek naar MetaMask/metamask-extension gestuurd om een pagina met de titel 'Hoe het werkt' toe te voegen. Deze pagina bevatte een lijst met veelgestelde vragen die op dezelfde manier was opgebouwd als de meeste React-lijsten met veelgestelde vragen:

// 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}

Ongeveer 5 minuten later reageerde de bot. De commissie verwees naar de gids search-hidden-content en maakte 3 punten:

  • Als je elk antwoord voorwaardelijk rendert, wordt het uit de DOM verwijderd. Samengevouwen tekst kan dan niet worden gevonden met de functie Zoeken op pagina van de browser en is moeilijker te ontdekken voor ondersteunende technologie.
  • Een systeemeigen <details>/<summary>-bekendmaking (Baseline sinds 2020) houdt de content in de DOM met de juiste semantiek. Voor elkaar uitsluitende deelvensters sluit een gedeeld name-kenmerk (Baseline, nieuw beschikbaar sinds 2024) de andere automatisch. Voor een veelgestelde vragen-sectie met meerdere geopende deelvensters laat je dit weg.
  • Als het team de voorkeur geeft aan de bestaande Disclosure-component, moeten de antwoorden in de DOM blijven met hidden="until-found" en een beforematch-listener die aria-expanded en de icoonstatus synchroniseert.
// After: Native <details> / <summary> disclosure (findable with find-in-page)
<details>
  <summary>
    <Text>{question}</Text>
  </summary>
  <Text>{answer}</Text>
</details>

13 minuten later publiceerde de auteur een oplossing. De component werd een systeemeigen <details>/<summary>-bekendmaking, samengevouwen antwoorden bleven in de DOM voor zoeken in-page en 2 navigatieknoppen werden links.

Die bot is een Cursor Automation die Modern Web Guidance uitvoert. Nepomuceno heeft de bot ingesteld met een prompt van 3 regels. Op 21 oktober 2026, na 5 weken:

  • De bot had ongeveer 480 pull-verzoeken uitgevoerd en op 64 daarvan gereageerd (57 pull-verzoeken voor functies en fixes, plus 7 geautomatiseerde release- en synchronisatie-pull-verzoeken) van 26 auteurs.
  • In de pull-verzoeken voor functies en oplossingen hebben engineers 43 van de bevindingen opgelost en 3 andere gedeeltelijk opgelost, verspreid over 22 pull-verzoeken.
  • De engineers handelden snel: van de 38 oplossingen met een identificeerbare commit, werden er 19 binnen 15 minuten en 26 binnen een uur toegepast, met een mediaan van 15,2 minuten van opmerking tot oplossing.

Hieronder vind je hoe MetaMask de bot heeft ingesteld, wat de bot heeft gevonden en waar de bot te veel ruis veroorzaakte.

De instelling is een prompt van 3 regels

Op de vraag hoe de automatisering is ingesteld, antwoordde Nepomuceno: "Onze instellingen zijn eigenlijk heel gewoon. We houden het beknopt en beperkt." De hele instructie:

- 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

Hoe dat in de praktijk werkt:

  • De bot geeft advies: In de eerste 2 dagen postte de bot reviews met het verzoek om wijzigingen (en één goedkeuring), die auteurs afwezen nadat ze de wijzigingen hadden doorgevoerd. Sinds 18 september is elke review een reactie. Het blokkeert een samenvoeging niet, dus auteurs hebben het laatste woord over elke suggestie.
  • De bot citeert specifieke handleidingen en bestanden in de repository: In de 64 pull-verzoeken waarop de bot reageerde, heeft deze 122 bevindingen naar voren gebracht. Van de 102 pull-verzoeken voor functies en fixes noemen 63 de specifieke Modern Web Guidance-handleiding die ze toepassen, zoals search-hidden-content, state-aware-sticky-headers of sms-otp-form, en verwijzen ze naar een bestaand bestand in de repository als het al het aanbevolen patroon gebruikt.
  • De bot blijft stil, tenzij een pull-verzoek de UI raakt: Van de ongeveer 480 pull-verzoeken in die 5 weken raakten er minstens 100 de UI of clientcode. De bot vond gemiddeld 2 problemen per pull-verzoek waarop deze reageerde. Teams met voornamelijk frontend-repository's kunnen verwachten dat de tool op een groter deel reageert.

De prompt zelf werkt met elke agentrunner. Modern Web Guidance wordt geïnstalleerd als een vaardigheid of plug-in voor Cursor, Claude Code, Codex, GitHub Copilot, Antigravity en andere programmeeragents. Wanneer een agent de vaardigheid uitvoert, zoekt deze de overeenkomende handleidingen op in een lokale index zonder dat er API-sleutels nodig zijn. De agent controleert de verschillen met de handleidingen met het model dat de agentrunner van het team al biedt.

Wat Modern Web Guidance opmerkt dat linters niet opmerken

Een statische linter kan een ontbrekend kenmerk op een enkel element markeren, maar de bevindingen die volgen, kwamen neer op interactiegedrag, HTML-semantiek en hoe componenten in verschillende bestanden bij elkaar passen.

Een veld voor transactiekosten dat bewerkbaar leek, maar invoer negeerde

In de geavanceerde instellingen voor transactiekosten van MetaMask leek het veld voor de gaslimiet (die de netwerkkosten beperkt die een transactie kan verbruiken) bewerkbaar, maar werd de invoer van gebruikers genegeerd. Dit gebeurde als een schatting van de kosten nog werd geladen of was mislukt. Ondertussen was de knop Opslaan uitgezet, zonder uitleg die ondersteunende technologie kon lezen.

De bot citeerde de formulierenhandleiding en markeerde 3 oplossingen:

  • Zet het veld voor de gaslimiet uit als er geen schatting beschikbaar is en koppel de zichtbare statustekst aan het veld, zodat ondersteunende technologie de uitleg voorleest.
  • Koppel de uitgeschakelde knop Opslaan aan dezelfde statustekst, zodat schermlezers weten waarom de knop is uitgeschakeld.
  • Zet het veld op een numerieke invoermodus, zodat mobiele gebruikers een numeriek toetsenblok krijgen.

De auteur paste alle 3 de oplossingen toe op beide instellingsmodals en voegde ze samen tot één component.

In een statusbanner voor een van de handelsfuncties van MetaMask waren de inline acties Veelgestelde vragen en Contact opnemen met MetaMask-support gebouwd als knoppen die een nieuw tabblad openden met JavaScript in plaats van als links. Binnen 3 minuten gaf de bot, op basis van de handleidingen voor HTML en toegankelijkheid, aan dat schermlezers ze aankondigen als knoppen en dat gebruikers linkmogelijkheden verliezen, zoals de URL kopiëren of openen in een nieuw tabblad via het contextmenu. Het wees ook naar een bestaande bannercomponent in de codebase van MetaMask die deze acties al als echte links weergeeft.

12 minuten later veranderde de auteur beide acties in links. "Ik vind het erg nuttig dat als een richtlijn eenmaal is overgenomen, toekomstige beoordelingen die vermelden als referentievoorbeeld," aldus Nepomuceno.

Verificatie-invoer waarvan de labels ergens anders stonden

De mogelijkheid van de bot om meerdere bestanden te lezen, bleek ook nuttig bij een formulier met meerdere stappen. Een statische linter ziet alleen een tekstveld met tijdelijke aanduidingstekst in elke stap en kan niet zien dat de zichtbare kop en instructies zich in een bovenliggende indelingscomponent bevinden. De bot citeerde de handleidingen voor formulieren en toegankelijkheid en ontdekte dat de tijdelijke aanduiding het enige label van het veld was, dat de staptitel en instructies in de bovenliggende indeling niet aan de invoer waren gekoppeld en dat foutmeldingen en berichten over opnieuw gestuurde codes niet werden voorgelezen door schermlezers. Een kwartier later waren alle 3 de problemen opgelost. De toegankelijkheidsbedrading bleef intact toen een volgend pull-verzoek de code-invoer opnieuw vormgaf als 6 visuele cijfervakken.

Nog een paar dingen die de bot heeft gevonden

Nog 5 bevindingen uit dezelfde periode van 5 weken:

  • Een CSS-detail dat de ontwikkelaar van de bot over het hoofd had gezien: Nepomuceno's eigen pull-verzoek voor vastgezette tabbladen op de homepage bevatte geneste CSS-scrollstatusquery's zonder de containers een naam te geven en schakelde een rand in op een manier die de indeling tijdens het scrollen veranderde. De bot verwees naar de handleiding voor statusbewuste vastgezette koppen, en hij loste beide problemen op. Hij vond de reviews nuttig voor ankerpositionering en scroll-state-query's.
  • Slippage beperkt tijdens toetsaanslag: Aangepaste slippage-invoer (de prijsbeweging die een gebruiker tolereert bij een transactie) beperkte waarden boven 100% bij elke toetsaanslag, waardoor 101 in 100 veranderde terwijl de gebruiker nog aan het typen was. Volgens de handleiding voor formulieren is de validatie verplaatst naar het moment waarop het veld de focus verliest en is er een zichtbare waarschuwingsbanner toegevoegd.
  • Een laadindicator die schermlezers niet konden gebruiken: Een laadskelet voor een tokenlijst plaatste het label 'laden' op een algemeen element zonder rol, wat ARIA verbiedt. De bot wees op 2 componenten in de codebase die het patroon voor alleen schermlezers van MetaMask al gebruikten (beide geüpdatet na een Modern Web Guidance-beoordeling 6 dagen eerder). De auteur paste de skeleton 8 minuten later aan dat patroon aan.
  • Onbeveiligde asynchrone actie: Een asynchrone knop Bekijken op provider had geen in-flight-beveiliging, waardoor een dubbelklik dubbele tabbladen en achtergrondwatchers kon openen. De auteur voegde een beveiliging toe minder dan 4 minuten na de reactie.
  • Toetsaanslagvalidatie zonder formulier: Een pagina voor het importeren van NFT's werd gevalideerd bij elke toetsaanslag en had geen <form>-element voor de semantiek van het indienen. Beide zijn opgelost 19 minuten na de beoordeling.

Elke review is openbaar. De volledige reacties van de bot staan bij elk gekoppeld pull-verzoek. Je kunt ze allemaal bekijken op GitHub.

Wat er niet is opgelost en hoeveel ruis er is

Niet elke bevinding is geland. In de volgende tabel staat hoe MetaMask de 102 bevindingen heeft geteld voor pull-verzoeken voor functies en oplossingen (nog eens 20 bevindingen kwamen terecht in 7 pull-verzoeken voor releases en synchronisatie, waarbij een beoordeling naar verwachting de code niet zou wijzigen):

Resultaat Bevindingen Opmerkingen
Vast 43 23 bevestigd door de auteur, 20 zichtbaar in latere commits
Gedeeltelijk opgelost 3 Gedeeltelijk toegepast of toegepast en daarna teruggedraaid
Geweigerd of fout-positief 16 Buiten bereik, opzettelijk of al gedaan
Niet behandeld 20 Geen wijziging (de auteur was het met een van deze eens)
Onbekend 20 Open pull-verzoek of datalimiet, zonder antwoord
Totaal 102 In 57 pull-verzoeken voor functies en oplossingen

Opgesplitst per thema voor alle 122 bevindingen (waaronder de 20 over release- en synchronisatie-pull-verzoeken):

Thema Alle bevindingen Bij pull-verzoeken voor functies en oplossingen Vast Gedeeltelijk opgelost
Toegankelijkheid 47 38 12 1
HTML-semantiek en CSS 18 16 9 2
Formulieren en invoer 15 15 10 0
Prestaties 15 11 6 0
Browserfuncties en -compatibiliteit 11 6 3 0
Anders 16 16 3 0
Totaal 122 102 43 3

Een paar patronen in die cijfers:

  • Oplossingen die binnen één component blijven, worden veel vaker toegepast dan toegankelijkheidswijzigingen die meerdere componenten beïnvloeden. Formulier- en HTML-correcties blijven binnen de component die wordt beoordeeld, dus auteurs passen ze meestal meteen toe (19 van de 31 opgelost). Toegankelijkheid had de meeste bevindingen (38), maar er werden er maar 12 opgelost, meestal omdat de oplossing buiten het bereik van het pull-verzoek viel of een gedeelde ontwerpsysteemcomponent nodig had die nog niet bestond.
  • 'Overig' is waar het afwijkt van de richtlijnen voor webplatforms. Zestien bevindingen hadden betrekking op de consistentie van het ontwerpsysteem, logische bugs, tekst, testkwaliteit, de donkere modus en codehygiëne. Er werd actie ondernomen op 3 bevindingen, waarvan er één een echte regressie was (een wijziging in de netwerklijst waardoor het vooraf invullen van formulieren niet meer werkte). De meeste van die 16 waren makkelijk te negeren, maar door die regressie waren ze een snelle blik waard.
  • Fout-positieven kwamen voort uit de manier waarop de agent de handleidingen toepaste. De meeste ruis kan worden opgelost in de instellingen. Omdat de beoordelingsbot een agent is die een diff leest in plaats van een statische linter, kwamen de fout-positieven voort uit het verkeerd lezen van de omringende code of het strenger toepassen van een regel dan de gekoppelde handleiding doet. De release- en synchronisatiebranches overslaan en de prompt aanscherpen zodat de agent zich houdt aan de regels die expliciet in een handleiding staan, zijn de voor de hand liggende volgende aanpassingen.

Nepomuceno beschrijft het bredere effect op het team en de doorlooptijd van beoordelingen:

'De reviews zijn heel nuttig. Ze hebben onze technici geholpen om moderne API's zoals interest invokers en de Popover API te ontdekken en ermee vertrouwd te raken."

"De beoordelingstijd voor PR is niet toegenomen, maar waarschijnlijk juist afgenomen. Veel technici gebruiken agents om de feedback te verwerken. De problemen die Modern Web Guidance heeft gevonden, zouden anders een menselijke reviewer hebben vereist die bekend is met deze moderne webtechnieken."

— Francis Nepomuceno, UX-technicus, MetaMask

MetaMask-engineer David Murdoch heeft ook bijgedragen aan de richtlijnen zelf: toen de CSS-lay-outhandleiding een fout bevatte in een van de voorbeelden, diende hij een probleem in. Het Modern Web Guidance-team voegde 2 dagen later een correctie samen.

Wat MetaMask een team zou vertellen dat overweegt om het te gebruiken

  • Lees de richtlijnen voordat je iets schrijft. Voer npx modern-web-guidance@latest search "accordion find in page" uit om te zien welke handleidingen een agent zou ophalen voor een taak. Je kunt ook de hele set gidsen voor Modern Web Guidance doornemen.
  • Begin met de prompt van 3 regels en de agent die je al uitvoert. Installeer de vaardigheid (npx modern-web-guidance@latest install of de plug-inopdracht van een agent), richt deze op alles wat kan worden uitgevoerd op pull-verzoeken en geef de vaardigheid de opdracht om alleen te reageren als er iets actie vereist en zich te houden aan de regels die expliciet in een handleiding staan. De bot stilhouden als er niets aan de hand is, is de reden waarom de technici van MetaMask de reacties nog steeds lezen.
  • Verwacht dat sommige bevindingen niet worden aangepakt. Van de 102 bevindingen over pull-verzoeken voor functies en oplossingen zijn er 43 opgelost en 36 geweigerd of niet behandeld. Die verhouding werkt goed voor een adviserende beoordelingsbot, maar zou storend zijn als blokkerende controle.
  • Laat mensen de beoordelingen uitvoeren. De bot is goed in semantiek van webplatforms, moderne CSS en interactiepatronen, maar kent het product niet.

Er is ook iets wat MetaMask nog niet heeft gemeten: na 5 weken heeft het team nog geen kosten per pull-verzoek, runtime, modelvergelijkingen of het gedrag van de beoordelingsbot buiten een React-codebase bijgehouden.

Met 3 regels configuratie kreeg MetaMask een beoordelingsbot die een specifieke gids citeert voor de meeste bevindingen (en een bestaand voorbeeld in de repository als er een bestaat). De geaccepteerde suggesties worden meestal binnen een uur opgelost.