Astro

Enhance Astro HTML without adding a React runtime to the page.

Enhance existing HTML

The adapter matches text nodes, inserts images, and observes content added later. Keep it outside framework-managed islands.

src/pages/chat.astro
<article data-emotes>Hello catJAM gg</article>

<script>
  import { fetchEmoteSet } from "react-7tv/core";
  import { enhance7tvContent } from "react-7tv/dom";

  const root = document.querySelector("[data-emotes]");
  if (root) {
    fetchEmoteSet("01M1M3EN0JK4ZWJAP3YPMQMV5T")
      .then((emotes) => enhance7tvContent(root, {
        emotes,
        excludeSelector: "astro-island",
      }))
      .catch(console.error);
  }
</script>

ClientRouter navigation

In a shared layout script, mount after page load and disconnect before the document swaps. Abort pending requests to avoid mounting into an old page.

Layout script
import { fetchEmoteSet } from "react-7tv/core";
import { enhance7tvContent, type ContentController7tv } from "react-7tv/dom";

let controller: ContentController7tv | undefined;
let request: AbortController | undefined;

function cleanup() {
  request?.abort();
  controller?.disconnect();
}

async function mount() {
  cleanup();
  const root = document.querySelector("[data-emotes]");
  if (!root) return;
  const current = new AbortController();
  request = current;
  try {
    const emotes = await fetchEmoteSet("global", {
      signal: current.signal,
    });
    if (current.signal.aborted || !root.isConnected) return;
    controller = enhance7tvContent(root, {
      emotes, excludeSelector: "astro-island",
    });
  } catch (error) {
    if (!current.signal.aborted) console.error(error);
  }
}

document.addEventListener("astro:page-load", () => { void mount(); });
document.addEventListener("astro:before-swap", cleanup);

React islands

With @astrojs/react, keep Provider7tv and Text7tv together in a .tsx component and render it with client:load. A React provider does not transform the surrounding Astro HTML.

NextSyntax & images