Embedded site stuck at "Loading Discussions"

AI-generated summary

Users are experiencing issues with embedding Discourse comments in Next.js applications, where the embed gets stuck on “Loading Discussions…” despite correct configuration and no console errors. Edrian_C_Bertulfo reported the issue and confirmed following the official embedding guide, but still encountered the problem. Lilly suggested reviewing the official embedding documentation, but it didn’t resolve the issue. Graemef and jfrux confirmed similar behavior — the embed sometimes loads only after refreshing the page, indicating a possible issue with the iframe’s state not updating after topic creation. Graemef shared a working React component for Next.js that uses useEffect to initialize the embed script and manages cleanup, though it still requires manual refresh to display comments. The community is seeking a solution that avoids forcing users to refresh, possibly through a callback or state update mechanism, which may not be currently supported by the embed script.

Hello! I have this issue when trying to embed Discourse to our NextJS Web App. I already tried searching for answers from the already existing thread that touches on the same error, but I haven’t been able to find a resolution for my issue.

Here’s how our embed code looks like:

<script id="discourse" type="text/javascript" data-nscript="afterInteractive">DiscourseEmbed = {
              discourseUrl: 'https://qanvast.discourse.group/',
              discourseEmbedUrl: 'https://web-uat.qanvast.com/sg/interior-design-singapore/forefront-interior-the-alcove-26226?image=769596',
              // className: 'CLASS_NAME',
            };

            (function() {
              var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
              d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
              (document.getElementsByTagName('head')[0] 
              || document.getElementsByTagName('body')[0]).appendChild(d);
            })();</script>

In the front-end, it’s just stuck in “Loading Discussions…”. At first I thought it has something to do with the CSP, but I already added the domain to the Embedding Allowlist. No errors show up in the console logs nor the Network calls.

I’ve been stuck at this for a few hours now so I’d appreciate any help.

Hi @Edrian_C_Bertulfo welcome :wave:

Did you follow this topic? This is how to do it, but I have no idea if it will work for a NexJS web app…

Hello Lilly!

Thank you for your response. I did follow the instructions on that post, and I’m still stuck with the infinite “Loading Discussion…” issue.

Did you ever figure it out?

I have this issue using next.js too. It is stuck on ‘loading discussion’ for the first load (before topic creaed). If i refresh, the comments/start discussion shows - so it creates the topic fine for me, but doesn’t update the loading state (have to refresh to show updated state with comment box).

It’d be good if there was a callback or something to let you know the topic is created as it’s not ideal to have to refresh the page. I don’t know if that is possible with an iframe

Hmm, it doesn’t actually ever load, even after the topic creates…
At least not for me.

Any tips?

Here’s what I have in my next app. It works how I mentioned previously - have to press refresh. Lemme know if it works.

Sometimes i have ot refresh a few times or wait for a while then refresh to get pas tthe ‘loading discussion’ message

<DiscourseComments
          discourseUrl="https://discourseurl.com/"
          discourseEmbedUrl={embedUrl}
          username="system"
        />

component:

"use client"

import { useEffect, useRef } from "react"

/**
 * A React component to embed Discourse comments on a website
 *
 * @param {Object} props - Component props
 * @param {string} props.discourseUrl - The URL of your Discourse instance (including trailing slash)
 * @param {string} [props.discourseEmbedUrl] - The URL of the current page (for auto topic creation)
 * @param {number} [props.topicId] - ID of an existing Discourse topic (alternative to discourseEmbedUrl)
 * @param {string} [props.username] - Username for topic creation
 * @param {string} [props.className] - CSS class name to add to the embed
 * @param {string} [props.referrerPolicy] - Referrer policy for the iframe
 */
export default function DiscourseComments({
  discourseUrl,
  discourseEmbedUrl,
  topicId,
  username,
  className,
  referrerPolicy = "no-referrer-when-downgrade",
}) {
  const initialized = useRef(false)

  useEffect(() => {
    // Prevent duplicate initialization
    if (initialized.current) return
    initialized.current = true

    // Validate required props
    if (!discourseUrl) {
      console.error("DiscourseComments: discourseUrl is required")
      return
    }

    if (!discourseEmbedUrl && !topicId) {
      console.error("DiscourseComments: Either discourseEmbedUrl or topicId must be provided")
      return
    }

    // Configure the Discourse embed
    const config = {
      discourseUrl,
      discourseReferrerPolicy: referrerPolicy,
    }

    if (discourseEmbedUrl) {
      config.discourseEmbedUrl = discourseEmbedUrl
    }

    if (topicId) {
      config.topicId = topicId
    }

    if (className) {
      config.className = className
    }

    // Set the global DiscourseEmbed object
    window.DiscourseEmbed = config

    // Load the Discourse embed script
    const script = document.createElement("script")
    script.type = "text/javascript"
    script.async = true
    script.src = `${discourseUrl}javascripts/embed.js`
    document.head.appendChild(script)

    // Cleanup
    return () => {
      document.head.removeChild(script)
      delete window.DiscourseEmbed
    }
  }, [discourseUrl, discourseEmbedUrl, topicId, className, referrerPolicy])

  return (
    <>
      <div id="discourse-comments"></div>
      {username && <meta name="discourse-username" content={username} />}
    </>
  )
}