How to add comments to a Gatsby site
Integrate EchoThread comments into your Gatsby blog or docs site. A lightweight React component that loads after hydration — no heavy plugins.
On this page
Why Gatsby + EchoThread
Gatsby builds blazing-fast static sites with React, but its plugin ecosystem for comments is heavy — most solutions add large dependencies, require API routes, or need a separate backend.
EchoThread takes a different approach: a single sub-20 KB gzipped script that loads from a CDN. No Gatsby plugins, no GraphQL schema extensions, no build-time configuration. Create a simple React component and you're done.
Prerequisites
- A Gatsby site (v4+)
- An EchoThread account — create one free
- Your site's API key from the EchoThread dashboard
Step 1 — Create the component
Create src/components/EchoThread.jsx:
import React, { useEffect, useRef } from 'react'
export default function EchoThread({ pageId, pageTitle, pageUrl }) {
const loaded = useRef(false)
useEffect(() => {
if (loaded.current) return
loaded.current = true
const script = document.createElement('script')
script.src = 'https://cdn.echothread.io/widget.js'
script.async = true
document.body.appendChild(script)
return () => script.remove()
}, [])
return (
<div
id="echothread"
data-api-key="YOUR_API_KEY"
data-identifier={pageId}
data-page-title={pageTitle}
data-page-url={pageUrl}
/>
)
}
useEffect hook only runs in the browser, so the script is never loaded during Gatsby's server-side build. The container div renders as static HTML and the widget initializes after hydration.
Step 2 — Use in a blog template
Import the component in your blog post template and pass data from GraphQL:
import React from 'react'
import { graphql } from 'gatsby'
import EchoThread from '../components/EchoThread'
export default function BlogPost({ data }) {
const post = data.markdownRemark
return (
<article>
<h1>{post.frontmatter.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
<EchoThread
pageId={post.fields.slug}
pageTitle={post.frontmatter.title}
pageUrl={`https://example.com${post.fields.slug}`}
/>
</article>
)
}
export const query = graphql`
query BlogPostBySlug($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
fields { slug }
frontmatter { title }
}
}
`
MDX pages
If you use gatsby-plugin-mdx, you can either:
Option A: Add the component in your MDX page template (recommended):
import EchoThread from '../components/EchoThread'
export default function MdxPost({ data, children }) {
return (
<article>
{children}
<EchoThread
pageId={data.mdx.fields.slug}
pageTitle={data.mdx.frontmatter.title}
pageUrl={`https://example.com${data.mdx.fields.slug}`}
/>
</article>
)
}
Option B: Import the component directly in an MDX file:
import EchoThread from '../components/EchoThread'
Your content here...
<EchoThread pageId="my-post" pageTitle="My Post" pageUrl="https://example.com/my-post" />
Theming
Add optional theme and accent color props:
<EchoThread
pageId={slug}
pageTitle={title}
pageUrl={url}
theme="dark"
accentColor="#7c3aed"
/>
Add the props to the component the same way as shown in the Next.js TypeScript example.
Disable per page
Add a comments field to your frontmatter and conditionally render:
{post.frontmatter.comments !== false && (
<EchoThread
pageId={post.fields.slug}
pageTitle={post.frontmatter.title}
pageUrl={url}
/>
)}
Troubleshooting
Comments don't appear
- Check your API key in the dashboard.
- Make sure the domain matches (including
localhost:8000for Gatsby dev). - Open the browser console for errors.
"window is not defined" during build
This shouldn't happen since all DOM access is inside useEffect. If you see this error, make sure you're not calling the component outside of a React render cycle (e.g. in gatsby-ssr.js).
Widget doesn't update on navigation
Gatsby uses client-side routing by default. If comments don't update when navigating between posts, verify that the pageId prop changes. The widget reinitializes when its container's data attributes change.
Ready to add comments to your Gatsby site?
Free during beta. Set up in under 5 min.
Create free account