Skip to content

Create a Viewer Panel

This viewer panel displays the broadcaster's current message and updates immediately when MEDKit receives a new motd event. Complete Install MEDKit manually first, then add the files below.

Create the panel HTML

panel.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Message of the Day</title>
  </head>
  <body>
    <main>
      <h1>Message of the Day</h1>
      <p id="motd" aria-live="polite">Loading…</p>
    </main>
    <script type="module" src="/src/panel.js"></script>
  </body>
</html>

Read state and listen for updates

The initial state read handles viewers who open the panel after the latest message was sent. The listener handles messages sent while the panel is open.

src/panel.js
import Muxy from "@muxy/extensions-js";

async function main() {
  if (import.meta.env.DEV) {
    const debugging = new Muxy.DebuggingOptions();
    debugging
      .channelID(import.meta.env.VITE_CHANNEL_ID)
      .role("viewer");
    Muxy.debug(debugging);
  }

  Muxy.setup({ clientID: import.meta.env.VITE_CLIENT_ID });
  const medkit = new Muxy.SDK();
  await medkit.loaded();

  const message = document.querySelector("#motd");
  const state = await medkit.getChannelState();
  message.textContent = state.motd ?? "Enjoy the show!";

  medkit.listen("motd", (event) => {
    message.textContent = event.motd;
  });
}

main().catch((error) => {
  console.error(error);
  document.querySelector("#motd").textContent = "Unable to load the message.";
});

For local testing, set VITE_CLIENT_ID and VITE_CHANNEL_ID in .env.local, run npm run dev, and open the panel.html URL printed by Vite. Remove the debug configuration from production bundles; Twitch supplies the authenticated viewer context there.

Continue with Create a broadcaster panel.