cd /news/developer-tools/html-is-getting-cool-again-meet-the-… · home topics developer-tools article
[ARTICLE · art-107003] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

HTML is getting cool again: Meet the Invoker Commands API

The Invoker Commands API lets developers declaratively control interactive elements like dialogs and popovers directly in HTML, reducing the need for JavaScript boilerplate. The API, now Baseline 2025 with cross-browser support since December 2025, shifts responsibility from application state to the browser, and works with frameworks like React via JSX properties.

read3 min views1 publishedAug 22, 2026

For years, frontend development has had a slightly embarrassing relationship with HTML. We all read about semantic HTML, we talk about using the right landmarks, the right attributes, accessible forms, and meaningful elements. And then we go back to writing React.

While the whole industry is obsessed with AI, browsers are shipping features that make the platform even more capable. Features that let us remove JS, reduce state, and express UI behaviour in HTML. But since AI is trained in the past, these are ignored or not recommended enough through old patterns.

Historically, in order to open a dialog or a popover, we need a chunk of custom boilerplate code.

<button id="open-dialog">Open dialog</button>
<dialog id="my-dialog">
  <p>Dialog content</p>
  <button id="close-dialog">Close</button>
</dialog>

<script>
  const dialog = document.getElementById("my-dialog");
  document.getElementById("open-dialog").addEventListener("click", () => {
    dialog.showModal();
  });
  document.getElementById("close-dialog").addEventListener("click", () => {
    dialog.close();
  });
</script>

We need a button to open our dialog, the dialog itself, and then we write JS to explain the interaction to the browser: "When the user clicks the button, open the dialog".

If you're using React or Vue, this can get even more elaborate: You need some custom state, potentially pass it to your component, wire up an event handler, and then make sure everything stays in sync.

Whether vanilla or framework, the code above is completely reasonable on its own, every frontend developer has written something similar a hundred times. But after writing it for the thousandth time, it made me wonder: do we really need application state to represent that a dialog is open? The answer is: it depends. Sometimes state is needed. But sometimes we're just rebuilding behaviour that HTML and the browser can already provide for us out of the box in 2026.

The Invoker Commands API provides us a way to declaratively assign behaviours to buttons, which then allows us to control these interactive elements. Instead of adding an event listener we can describe the relationship directly in HTML.

The attributes that help us are commandFor

and command

:

<button commandfor="mycoolpopover" command="toggle-popover">
  Toggle the popover
</button>
<section id="mycoolpopover" popover>
  <button commandfor="mycoolpopover" command="hide-popover">Close</button>
  Awesome Popover content
</section>

All of these are transferable to your framework of choice:

export function DeleteButton() {
  return (
    <>
      <button command="show-modal" commandFor="delete-dialog">
        Delete account
      </button>
      <dialog id="delete-dialog">
        <h2>Delete account?</h2>
        <p>This cannot be undone.</p>
        <button command="close" commandFor="delete-dialog">
          Cancel
        </button>
      </dialog>
    </>
  );
}

The important detail here is that React's JSX property is commandFor, while the resulting HTML attribute is commandfor

At a first glance this looks like saving, maybe 10 lines of code. That's nice. But the most interesting is the shift of the responsibilities from us, back to the browsers.

The browser isn't becoming less capable because we're writing less JavaScript, but rather the opposite. We finally need less JS.

Now, before everyone starts deleting their dialogs, there is a small catch: The Invoker Commands API is new. MDN currently lists it as Baseline 2025, with cross-browser availability in the latest browser versions since December 2025. Older browsers may not support it.

── more in #developer-tools 4 stories · sorted by recency
── more on @invoker commands api 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/html-is-getting-cool…] indexed:0 read:3min 2026-08-22 ·