Docs menu
Add comments to a Next.js site
next/script,
then put a container on the page that renders a post. Readers can click from post to post and each one shows its own thread.
Before you start
- A Disfora project for your site. Create a free account, start a project and enter your domain. You'll verify it once the code is live.
App Router
Add the script to your root layout, app/layout.tsx:
import Script from 'next/script';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Script src="https://disfora.com/public/disfora.js" strategy="afterInteractive" />
</body>
</html>
);
}
Then add the container where comments should appear, for example after the post body in app/blog/[slug]/page.tsx:
export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost(slug);
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
<div data-disfora-comments />
</article>
);
}
The container is a plain element, so the page can stay a Server Component. You don't need
'use client'. For a star rating as well, add <div data-disfora-ratings /> where it
should go.
Pages Router
Add the script to pages/_app.tsx, so it loads once for the whole app:
import type { AppProps } from 'next/app';
import Script from 'next/script';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<Script src="https://disfora.com/public/disfora.js" strategy="afterInteractive" />
</>
);
}
Then put <div data-disfora-comments /> in your post page, for example pages/blog/[slug].tsx.
Moving between posts
<Link> changes the page without a reload. Disfora notices the new address and the new container,
and loads that post's comments. Pages without a container, like your home page, show nothing, and the comments code
only downloads once a reader opens a post. You don't need a key or any code that reloads the widget.
Each post's thread belongs to its address, so /blog/hello and /blog/hello?ref=twitter share
one thread. See how pages are matched.
It works the same with a static export (output: 'export'): the script and container are plain HTML.
Check it on your site
Disfora only loads on the domain in your project, so localhost:3000 won't show it. Deploy, then
verify your domain if you haven't yet, and open a post on your
live site.
Ask a question
Something missing or unclear? Ask here and we'll answer in the thread.
Updated October 2026