Skip to content
A Astro Rocket

Comments on Blog Posts — Giscus, Cusdis, or Artalk, Lazy-Loaded

Astro Rocket's blog comments are pluggable: pick Giscus, Cusdis, or the fully self-hosted Artalk. All three lazy-load on scroll — skip them and you pay nothing.

H

Hans Martens

7 min read

Astro Rocket supports comments at the bottom of blog posts. The feature is pluggable: a single provider switch picks between Giscus (comments stored in a GitHub Discussions thread), Cusdis (a lightweight widget you can use hosted or self-host), and Artalk (a full comment system you run entirely on your own server). Whichever you pick, the wiring underneath is the same careful setup.

It’s off by default. When disabled, no JavaScript and no network requests are added to your blog pages. When enabled, the provider’s script is lazy-loaded — it only downloads when the reader actually scrolls toward the comments section. Readers who never scroll that far pay zero performance cost.

Kept current. This post originally covered only Giscus. Comments are now pluggable: Cusdis was added first (a lightweight, optionally self-hosted widget), and Artalk followed as a fully self-hosted option — contributed by the community in #469 for people who want to own and moderate every comment on infrastructure they control. The setup below reflects the current, three-provider system. If you’re already on Giscus, nothing changed: provider defaults to 'giscus'.

Three providers, one switch

All three are wired the same way — server-rendered placeholder with reserved height (no layout shift), lazy-loaded on scroll, theme and language that follow the site by default. The difference is where the comments live and how much you run yourself:

Giscus Cusdis Artalk
Stores comments in A GitHub Discussions thread Cusdis (hosted) or your own instance Your own Artalk server
Infrastructure you run None (GitHub hosts it) None if hosted; a service if self-hosting A server + database, always
Commenter needs an account? Yes — a GitHub login No — name + email, optional No — name + email
You moderate / own the data? Via GitHub Discussions Hosted dashboard, or yourself Entirely yourself, on your server
Live light/dark sync Yes (postMessage) No — re-renders on toggle Yes (setDarkMode)
Reactions 👍 ❤️ 🎉 etc. Voting + emoji
Best for Dev-audience blogs already on GitHub General audiences, minimal setup Owning and self-hosting everything
  • Pick Giscus if your readers are developers who already have GitHub accounts and you’re happy storing the thread in a public repo — there’s no server to run.
  • Pick Cusdis if you’d rather not gate commenting behind a GitHub login and want the lightest setup — use the hosted service, or self-host later if you outgrow it.
  • Pick Artalk if you want to own and moderate everything — comment data, users, and moderation — on infrastructure you control, and you’re comfortable running a small service. Unlike Giscus and Cusdis, Artalk has no hosted option: you supply the server.

Step 1 — Set up your provider

If you choose Giscus

  1. Go to giscus.app.
  2. Pick the GitHub repo you want to host the discussions in. The repo must be public and have Discussions enabled (Settings → Features → Discussions).
  3. Install the Giscus app on that repo.
  4. Choose the discussion category (most people use “General” or create a dedicated “Comments” category).
  5. Copy the four values shown on the page: data-repo, data-repo-id, data-category, and data-category-id.

If you choose Cusdis

  1. Sign up at cusdis.com — or self-host it (Docker, Vercel, etc.) if you want to own the data.
  2. Create a website in the dashboard.
  3. Copy the App ID from the embed code it gives you (a UUID).
  4. Self-hosting? Note your instance URL — you’ll set it as host so the widget and its API point at your server instead of cusdis.com.

If you choose Artalk

Artalk is fully self-hosted — there’s no hosted service, so you run the backend yourself (see the Artalk docs; it ships as a single Go binary or a Docker image and stores comments in SQLite/MySQL/PostgreSQL).

  1. Deploy an Artalk server and note its public address. In production this must be an https:// URL — a plain http:// script is blocked as mixed content on an https site and is open to tampering.
  2. In the Artalk dashboard, create a site and note its site name (Artalk uses it for multi-site isolation).
  3. You’ll set the address as server and the name as site. That’s all Artalk needs; the client JS/CSS are served from your Artalk server by default.

Step 2 — Configure Astro Rocket

Open src/config/site.config.ts and find articleFeatures.comments. Flip enabled to true, set provider, and fill in that provider’s block:

articleFeatures: {
  comments: {
    enabled: true,
    provider: 'giscus', // 'giscus' | 'cusdis' | 'artalk'
    giscus: {
      repo: 'you/your-repo',
      repoId: 'R_kgDOAbcdef',
      category: 'General',
      categoryId: 'DIC_kwDOAbcdef',
      mapping: 'pathname',
      reactionsEnabled: true,
      theme: '', // empty → follow the site's light/dark mode
      lang: '',  // empty → follow the site's current locale
    },
    cusdis: {
      appId: '00000000-0000-0000-0000-000000000000',
      host: 'https://cusdis.com', // your URL when self-hosting
      theme: '', // empty → follow the site's light/dark mode
      lang: '',  // empty → follow the site's current locale
    },
    artalk: {
      server: 'https://comments.example.com', // your Artalk server (https in prod)
      site: 'My Blog', // the site name you created in Artalk
      // jsUrl / cssUrl: optional — override to serve the client from a CDN
      // darkMode: leave unset → follow the site's light/dark mode (live)
      // locale: leave unset → follow the site's current locale
    },
  },
},

Only the block matching provider needs real values — leave the others as-is. Build, deploy, and every blog post now has a comments section underneath.

The component fails soft: if the selected provider isn’t fully configured (Giscus missing any of its four IDs, Cusdis missing its App ID, or Artalk missing its server or site), it renders nothing rather than breaking the page. A half-finished enabled: true just stays invisible until you complete setup.

Theme and language follow the site

Leave the theme and language fields empty (the default) and the embed mirrors your site automatically:

  • Theme follows the visitor’s live light/dark choice, resolved from the same colour-mode system the rest of the site uses. Giscus and Artalk both update instantly when the visitor toggles — Giscus via its postMessage API, Artalk via its setDarkMode method. Cusdis has no live theme API, so on a toggle its thread is re-rendered — a brief reload. To opt out of site-following on Cusdis, set its theme to 'auto' (OS preference), 'light', or 'dark'; on Artalk, set darkMode to 'auto', true, or false.
  • Language follows the page’s current locale, so a /nl/blog/... post loads the comment widget in Dutch with no extra config.

Set the relevant field to a specific value to override the site-following behaviour.

Per-post override

Some posts don’t need comments — announcements, legal pages, or quick updates. Hide comments on a single post with frontmatter:

---
title: My announcement
comments: false
---

The site-wide setting stays on; just this post skips the comments block.

How the lazy-loading works

If the comment script were loaded on every article page-load, it would add a third-party script (and, for Giscus, an iframe) to every blog post — roughly 100 KB in Giscus’s case. That hurts Lighthouse scores and feels especially wasteful for readers who only skim the first paragraph.

So the component does this instead, regardless of provider:

  1. On the server, it renders an empty <div> with a reserved min-height: 360px (so there’s no layout shift when the widget later appears).
  2. On the client, an IntersectionObserver watches that <div>.
  3. When the reader scrolls within 300px of the comments area, the provider’s script is appended to the DOM and the widget loads.

Readers who bounce or skim → 0 KB. Readers who scroll to the bottom → the comments are ready by the time they arrive. To make that first request even faster, BaseLayout adds a <link rel="preconnect"> to the active provider’s host when comments are enabled, warming the DNS+TLS handshake before the script fires. (For Artalk, that’s your server’s origin.)

What it costs

Scenario Cost
Comments disabled (default) 0 KB, 0 requests
Enabled, reader doesn’t scroll to comments ~0.5 KB inline JS
Enabled, reader scrolls to comments Giscus ~100 KB; Cusdis much less; Artalk served from your own server — all async, below-the-fold, no LCP impact

The reserved min-height prevents CLS. The async load prevents render blocking. The IntersectionObserver prevents wasted requests. And because the comments component is a thin dispatcher, only the provider you selected ships its client script — the others are never bundled.

Where it lives

  • Dispatcher: src/components/blog/Comments.astro (renders the selected provider)
  • Providers: src/components/blog/CommentsGiscus.astro, CommentsCusdis.astro, and CommentsArtalk.astro
  • Wiring: src/layouts/BlogLayout.astro
  • Config: src/config/site.config.tsarticleFeatures.comments
  • Per-post override: comments: false in MDX frontmatter

For the full tour of site.config.ts, see the configuration guide.

That’s the entire feature. Pick a provider, paste a few values into your config, and your blog has a real comment thread — without a performance hit, and (with Giscus or hosted Cusdis) without a database to run yourself.

Share:

Related Posts

Table of Contents — Reading Anchors for Long Posts

Astro Rocket renders an optional TOC on blog posts in three layouts — inline card, sticky sidebar, or both — with the sidebar on the left or right. Pick what fits your audience.

H Hans Martens
5 min read
#astro-rocket #features #blog #navigation

YouTube in Your Posts — the Click-to-Play Embed

Embed a YouTube video in any post or page with one component. The page ships only a thumbnail; the player loads from youtube-nocookie.com when the reader presses play. Lighthouse stays at 100.

H Hans Martens
3 min read
#astro-rocket #features #components #performance

Video Slides in Project Galleries — Zero Bytes Until Play

Project carousels now accept self-hosted video slides next to images. Here's how to use them, how they work, and why they don't cost a single Lighthouse point.

H Hans Martens
4 min read
#astro-rocket #features #projects #performance

Follow along

Stay in the loop — new articles, thoughts, and updates.