How to Implement giscus using Nuxt 3


Sun Feb 02 2025
| 4 min read
|
Philip Rutberg Philip Rutberg

giscus logo

Integrating a comment system that scales and feels modern is crucial when building interactive web applications. Recently, after a recommendation by a great colleague (check out some of his work), I decided to enhance my Nuxt 3 project by adding giscus, a GitHub-powered commenting system that leverages Discussions. In this article, I'll walk you through how to implement giscus in Nuxt 3.

Setting Up the Environment

Let's start with a fresh Nuxt 3 project. If you haven't already, create one using the Nuxt CLI:

npx nuxi@latest init giscus-nuxt3

Once the project is set up, we install giscus for Vue:

npm install @giscus/vue

Integrating giscus into Your Nuxt 3 Project

To keep things organized, let's create a new Vue component for giscus. This component encapsulates all giscus configuration details.

Before proceeding, you'll need to retrieve your repository's ID and category details along with any other configuration options you may want. Visit Giscus and follow the documentation steps provided there. The website will guide you through getting your repo-id and category-id, as well as customizing other settings. Once you've completed the setup, copy the website's output and use it to replace the placeholder values below.

components/Giscus.vue
<script setup lang="ts">
import Giscus from '@giscus/vue';
</script>

<template>
  <Giscus
    repo="your-github-username/your-repo"
    repo-id="YOUR_REPO_ID"
    category="Announcements"
    category-id="YOUR_CATEGORY_ID"
    mapping="pathname"
    reactions-enabled="1"
    emit-metadata="0"
    input-position="bottom"
    theme="light"
    lang="en"
    loading="lazy"
  />
</template>

Replace the placeholder values with your actual GitHub repository details and category IDs. If you're unsure how to obtain these values, refer to the giscus documentation.

Working with Private Repositories (Optional)

If your main repository is private, you might run into access restrictions with giscus. A common workaround is to create a dummy public repository exclusively for hosting discussions. Create a dummy repository, enable Discussions in its settings, and generate your configuration values using that repository on giscus.

Example: Dynamic Articles with giscus Comments

If your repository is private, you might encounter issues using giscus directly due to access restrictions. A common workaround is to create a dummy public repository specifically for hosting discussions. Here’s what you can do:

  1. Create a new public repository (this will serve as your dummy repository).
  2. Enable Discussions in the dummy repository settings.
  3. Follow the same setup process on giscus.app to generate your configuration values using this dummy repository.
  4. Use the generated repo-id and category-id from the dummy repository in your giscus component configuration.

This approach allows you to leverage giscus even if your main project repository is private, ensuring that the commenting system remains accessible to your users.

Below is a dummy example of a Nuxt page where the discussion thread is generated dynamically based on the article’s route. In this example, each article uses its route path as the unique identifier for its comment thread.

pages/[...slug].vue
<script lang="ts" setup>
import Giscus from '@giscus/vue';

const route = useRoute();
</script>

<template>
  <Giscus
    :id="`article-${route.path}-comments`"
    repo="your-github-username/your-dummy-repo"
    repo-id="REPO_ID"
    category="Articles"
    category-id="CATEGORY_ID"
    mapping="specific"
    :term="route.path"
    reactions-enabled="1"
    emit-metadata="0"
    input-position="top"
    theme="light"
    lang="en"
    loading="lazy"
  />
</template>

In this example, each article uses its route path as the unique identifier for its discussion thread. This dynamic approach ensures that every article gets its own comment section without any additional configuration.

Registering the Component Globally (Optional)

If you prefer using the giscus component across multiple pages without importing it everywhere, you can register it globally. Create a plugin file within the plugins directory:

plugins/giscus.client.ts
import Giscus from '@giscus/vue';

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component('Giscus', Giscus);
});

This setup ensures that the giscus component is available globally, simplifying its usage in any page.

Adding giscus to a Page

Now that the component is set up, integrating it into a page is straightforward. For example, in your page component:

pages/index.vue
<script setup lang="ts">
// No need to import Giscus if registered globally
</script>

<template>
  <section>
    <h1>Welcome to My Nuxt 3 Project</h1>
    <p>This is an example page demonstrating giscus integration.</p>
    <Giscus />
  </section>
</template>

<style scoped>
section {
  padding: 2rem;
}
</style>

And that's it! You've successfully integrated giscus into your Nuxt 3 project. The comment system should now be visible on the page.

Final Thoughts

Integrating giscus into this blog app was a smooth process. The combination of Vue 3's composition API and Nuxt 3's modularity made it effortless to add a modern comment system powered by GitHub Discussions. The flexibility in configuration means that you can always tweak the settings to suit your project's needs.

I hope this guide helps you bring a dynamic commenting experience to your own projects.

Happy coding, Philip!