Open-source project
SukkaW/DisqusJS avatar
SukkaW/DisqusJS

DisqusJS: rendering Disqus comments where Disqus itself is unreachable

:speech_balloon: Render Disqus comments in Mainland China using Disqus API

666 stars55 forksTypeScriptMIT

At a glance

What is it?
DisqusJS is a React and TypeScript embed that renders a read-only comment list from the Disqus API, so a blog in a censored network region can still show its comments by pointing at a reverse proxy. It can also detect whether the visitor can reach Disqus and fall back to the native embed, and it has no commenting of its own.
Who is it for?
Adopt DisqusJS if your site uses Disqus for comments and some of your visitors cannot reach the Disqus domains, and if a read-only comment list plus a reverse proxy is an acceptable outcome. Do not adopt it if you need commenting, moderation or threaded replies in the page, because DisqusJS deliberately provides only a read-only list, and do not expect the native Disqus features to survive in the regions where the proxy is in use.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 57 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A read-only comment list, not a comment system

DisqusJS is an Embed plugin built on the Disqus API and React, and it renders a read-only comment list through the Disqus API. Paired with a reverse proxy, that is what makes it possible to load the Disqus comment list in regions where the network is censored.

The read-only part is the defining constraint, and it is deliberate. The project describes itself as a pure front-end, ultra-lightweight implementation of a comment basic mode. The full Disqus mode, with the complete commenting experience, is the native Disqus embed, and DisqusJS is the fallback for when that cannot load.

The mechanism for choosing between them is automatic. The feature list says it judges whether the visitor can access Disqus and automatically selects either the comment basic mode or the full Disqus mode. That is a better design than hardcoding one path, because a site read by a mixed audience will have some readers who can reach Disqus and some who cannot, and the user should not have to configure per-visitor.

The rest of the feature set is small and specific: displaying the comment list, supporting sorting by newest, oldest and best, and working with React in frameworks such as Gatsby and Next.js. The project also says it automatically detects whether a visitor can access Disqus, and the demo sites are at disqusjs.skk.moe and blog.skk.moe. The library is MIT licensed, published on npm as disqusjs, and the last push to the repository was on 2026-08-27 with the release 3.2.2 on the same day.

Loading it from a CDN or from npm

The direct-in-HTML route requires two things: a stylesheet before the closing head tag, and a script where the comments should appear.

The stylesheet:

html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/browser/styles/disqusjs.css">

The script tag, plus a container element on the page:

html
<div id="disqusjs"></div>

The script itself can be loaded as a classic bundle or, if you only target modern browsers, as an ES module, and the package also provides the import form for bundlers:

sh
npm i disqusjs

When you install from npm you still have to bring the CSS in yourself, and the import path depends on the syntax level you want to target, with es2015, es2017 and es2022 builds all published:

js
import 'disqusjs/disqusjs.css';

The package manifest shows why there are so many entry points. The main, module and types fields all point at the es2015 build, and the exports map publishes a separate set for es2015, es2017 and es2022, each with its own types, import, module and default conditions, plus separate paths for the React styles and the React component itself. It is a package built for a wide range of consumers, from a plain HTML page to a React single-page app, and the build tooling behind it is rollup with a TypeScript configuration.

Initialising, rendering and the React component

The instance is created with a configuration object, and the documentation is careful that initialisation has to happen after DisqusJS has finished loading. The constructor takes the configuration directly:

js
const disqusjs = new DisqusJS({
    shortname: '',
    siteName: '',
    identifier: '',
    url: '',
    title: '',
    api: '',
    apikey: '',
    admin: '',
    adminLabel: ''
});

Rendering is then a separate call against a DOM node, and a CSS selector works as well:

js
disqusjs.render(document.getElementById('disqusjs'));

The React component takes the same properties, and the import path follows the same syntax-level convention:

jsx
import { DisqusJS } from 'disqusjs/react/es2015';

The property list in the documentation is where the real behaviour lives, and it is worth reading option by option because several of them have non-obvious defaults.

shortname is the Disqus forum shortname and is required with no default. siteName is the site name shown in the comment basic mode header, and it should match the Website Name in the Disqus admin settings. identifier is the current page identifier used to tell pages apart, and it is recommended with a default of document.location.origin plus the pathname plus the search string. url is the page URL that the Disqus crawler fetches for page metadata, recommended with the same default expression. title defaults to the page title, and exists so that a title containing the site name can be replaced with something cleaner in Disqus.

The interesting one is apikey, which is required and has no default. It accepts a string or an array of strings, and when an array is given a random key is used per request, which spreads the rate limit across several keys.

The API endpoint is the whole design decision

The api option sets the endpoint DisqusJS requests. The documentation says you should normally configure a reverse proxy of the Disqus API and put that proxy address in, and that you can alternatively use the official Disqus API endpoint or the proxy the author has set up. The recommended default is the author's proxy endpoint.

The reason the proxy exists is the Referrer and Origin check. The documentation describes the Disqus API application setup in detail: register an application, take the API key from the newly created application, and set the domain you use DisqusJS on in the application's settings, because the Disqus API checks the Referrer and Origin of API requests. A proxy that forwards to the official endpoint on the server's side sees a request from your own infrastructure, which is what makes the check pass for visitors in a region where the Disqus domains are unreachable.

Two further options exist for the same problem. The nesting option caps the maximum comment nesting depth, with a default of 4, and comments deeper than that are shown at the same level regardless of their parentage. The nocomment option is the message shown when there are no comments, and its default is a Chinese sentence about how quiet it is here with not a single comment.

And the disqusJsModeAssetsUrlTransformer is a function that rewrites asset URLs. The reason is that when DisqusJS loads in comment basic mode it still pulls some static assets from Disqus, such as user avatars, and those assets may be unreachable in some regions, and some browsers actively block all Disqus domains, with Mozilla Firefox in Enhanced Tracking Protection mode named as an example. The transformer lets you rewrite those URLs to something reachable, which is what stops avatars from failing to load.

Running a proxy on a serverless platform

Because the whole point is a proxy, the documentation explains how to set one up. Caddy or Nginx both work, and the endpoint that needs proxying is the Disqus API. The section then focuses on the serverless approach, for people who do not want to run a server or a backend program.

Vercel is described as a serverless platform whose free Hobby Plan provides 100 GiB of traffic per month and unlimited requests, and a separate example repository, a proxy example for DisqusJS, provides a sample configuration using the Now Router.

Cloudflare Workers is the other option, running JavaScript on Cloudflare, and its free plan is documented as providing 100000 requests per day.

Those numbers are the operational constraint that decides this design. A comment list is a handful of API requests per page view, so a plan with a hundred thousand requests a day covers a mid-sized site, and the traffic allowance is comfortable because the payloads are JSON comment lists rather than media. That arithmetic is also why a self-hosted proxy on a small VPS is viable for a blog, and why the author's shared proxy works as a default for people who do not want to operate one.

Single-page apps, PJAX, and the moderator badge

Two integration cases need separate handling, and the documentation is clear about both.

In a React SPA, a Next.js or a Gatsby site, using DisqusJS as a React component needs no extra steps: you change the props of the component and DisqusJS updates automatically. The reason is that the component owns the instance and re-renders it when the props change, which is a very different situation from a static page where the instance is created once.

A PJAX site is the opposite case, and the documentation says the instance must be destroyed manually before the page unloads and a new one created and rendered after the new page has loaded. The events to hook are the pjax send and pjax complete events, and the pattern is destroy on send, construct and render on complete, with fresh parameters such as a new identifier and url for the new page. Without that, the second page would show the first page's comments.

Separately, there is a small group of properties tied to the Disqus Moderator Badge, and the documentation is emphatic that a badge will not show if any one of them is missing. admin is the Disqus Moderator username, which is the site owner's own username, and adminLabel is the text shown in the badge, which should match the Moderator Badge Text in the Disqus admin settings. Both are optional with no default, and both are needed together for the badge to appear at all.

Where DisqusJS is the wrong choice

The first limitation is that it renders a read-only list, so a visitor in a censored region can read the comments and cannot post one, reply, vote or report. That is a deliberate trade and it is disclosed, but it is a degraded product for those users rather than a fix.

The second limitation is the dependency on Disqus itself. DisqusJS talks to the Disqus API, and the API is a third party service with its own rate limits, its own key management and its own terms. Your page still depends on a service you do not control, and the reverse proxy only changes where the request comes from, not whether Disqus is willing to serve it. The apikey array with random selection is a mitigation for rate limits rather than a solution, and an application whose key is rejected by the origin gets the same behaviour no matter where the request was made.

The third limitation is the reverse proxy as a dependency you now own. If you run your own, you are responsible for its availability, its certificate handling and its abuse exposure, since an open proxy in front of a third-party API is an invitation. If you use the author's shared endpoint, you are depending on a hobbyist's server for a feature of your production site, and the documentation does not describe a service level for it.

The real alternative, and it is the obvious one, is to not use Disqus. A self-hosted comment system, such as a Mastodon-compatible one, or a hosted provider you can reach from the regions you care about, removes the proxy and the API key from the picture entirely. The difference in approach is the whole point: DisqusJS keeps Disqus as the system of record and makes its content reachable through a workaround, while replacing the comment system removes the need for a workaround. If your audience is not in a censored region, or if you are starting a new site, choosing a comment system you can reach directly is the better answer, and DisqusJS is for the site that already has a Disqus archive and a reader base in the wrong place.

Editorial conclusion

Adopt DisqusJS if your site uses Disqus for comments and some of your visitors cannot reach the Disqus domains, and if a read-only comment list plus a reverse proxy is an acceptable outcome. Do not adopt it if you need commenting, moderation or threaded replies in the page, because DisqusJS deliberately provides only a read-only list, and do not expect the native Disqus features to survive in the regions where the proxy is in use. Before you deploy, register a Disqus API application, set the allowed domain in its settings so the Referrer and Origin checks pass, and decide whether you will run your own proxy or depend on the one the author hosts.

Frequently asked questions

What is DisqusJS?

It is a React and TypeScript embed that renders a read-only comment list from the Disqus API, so Disqus comments can be displayed in regions where the Disqus domains are unreachable by using a reverse proxy. It also detects whether the visitor can reach Disqus and picks the native Disqus embed or the basic comment mode automatically.

How do I install DisqusJS?

You can load it from a CDN with a stylesheet link and a script tag plus a container div, or install it from npm with npm i disqusjs, where the es2015, es2017 and es2022 builds are all published and the CSS still has to be imported separately. The package is MIT licensed and published as disqusjs, with the latest release being 3.2.2 from 2026-08-27.

What configuration does DisqusJS require?

shortname and apikey are required and have no default. identifier and url are recommended and default to the current origin, pathname and search string, and api is recommended and defaults to the author's proxy endpoint. apikey also accepts an array of keys, in which case one is chosen at random per request.

Why does DisqusJS need a reverse proxy for the Disqus API?

The Disqus API checks the Referrer and Origin of API requests, and you register an allowed domain in your Disqus application settings. A proxy forwards the request from your own infrastructure, so visitors in a region where the Disqus domains are unreachable can still load the comment list. The proxy endpoint to forward is the Disqus API endpoint, and the documentation shows how to run it on Vercel or Cloudflare Workers.

How does DisqusJS handle PJAX sites and React apps?

In a React SPA, a Next.js or a Gatsby site, using the React component needs no extra steps, because changing the component props updates DisqusJS automatically. In a PJAX site you must destroy the instance before the page unloads and construct and render a new one after the new page has loaded, with fresh parameters such as a new identifier and url.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. SukkaW/DisqusJS on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sukkaw-disqusjs.svg)](https://hysenlabs.com/projects/sukkaw-disqusjs)

Was this useful?