DEV Community

Yoni Ryabinski
Yoni Ryabinski

Posted on • Originally published at echothread.io

How to Add Comments to an Astro Site (Lazy-Loaded, Zero JS by Default)

Astro's "ship zero JavaScript by default" model is a perfect fit for comment widgets — they're the one thing on the page that actually needs to be interactive, and they're the perfect candidate for lazy loading.

Here's how to add EchoThread (privacy-first, no ads, under 15 KB gzipped, free during beta) to an Astro site as a reusable component.

1. Get an API key

Sign up at echothread.io, add your domain, copy the key.

2. Add the key to .env

PUBLIC_ECHOTHREAD_API_KEY=YOUR_API_KEY
Enter fullscreen mode Exit fullscreen mode

The PUBLIC_ prefix is required to expose it client-side.

3. Create src/components/EchoThread.astro

---
const apiKey = import.meta.env.PUBLIC_ECHOTHREAD_API_KEY;
const { theme = "auto" } = Astro.props;
---

<section class="echothread-wrapper">
  <div id="echothread" data-api-key={apiKey} data-theme={theme}></div>
  <script src="https://cdn.echothread.io/widget.js" defer></script>
</section>

<style>
  .echothread-wrapper {
    margin-top: 4rem;
    padding-top: 2rem;
    border-top: 1px solid var(--border-color, #e5e5e5);
    min-height: 400px;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

4. Use it in your post layout

---
import BaseLayout from "./BaseLayout.astro";
import EchoThread from "../components/EchoThread.astro";
---
<BaseLayout title={frontmatter.title}>
  <article>
    <h1>{frontmatter.title}</h1>
    <slot />
  </article>
  <EchoThread />
</BaseLayout>
Enter fullscreen mode Exit fullscreen mode

5. (Bonus) Lazy-load with IntersectionObserver

If you want true zero-JS until the reader actually scrolls to the comments:

<section id="echothread-section">
  <div id="echothread" data-api-key={apiKey}></div>
</section>

<script>
  const section = document.getElementById("echothread-section");
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      const s = document.createElement("script");
      s.src = "https://cdn.echothread.io/widget.js";
      s.defer = true;
      document.body.appendChild(s);
      observer.disconnect();
    }
  }, { rootMargin: "200px" });
  observer.observe(section);
</script>
Enter fullscreen mode Exit fullscreen mode

Now the widget script never loads for readers who don't scroll past the post.

Done

The widget identifies threads by page URL automatically. Works with content collections, MDX, static or SSR builds.

Full guide with troubleshooting: echothread.io/docs/guides/astro

Top comments (0)