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
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>
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>
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>
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)