原文章:How to integrate Giscus comments into AstroPaper
在像 GitHub Pages 这样的平台上托管一个简单的静态博客有许多优点,但也失去了一些互动性。幸运的是,Giscus 的存在为静态网站嵌入用户评论提供了一种解决方案。
Table of contents
Open Table of contents
Giscus 如何工作
Giscus 使用 GitHub API 来读取和存储在与存储库关联的 Discussions 中由 GitHub 用户发表的评论。
在您的网站上嵌入 Giscus 客户端脚本包,使用正确的存储库 URL 进行配置,用户就可以查看和撰写评论(在登录 GitHub 的情况下)。
这种方法是无服务器的,因为评论存储在 GitHub 上,并通过客户端动态加载,因此非常适合像 AstroPaper 这样的静态博客。
Setting up Giscus
Giscus can be set up easily on giscus.app, but I will outline the process shortly still.
Prerequisites
Prerequisites to get Giscus working are
- the repository is public
- the Giscus app is installed
- the Discussions feature is turned on for your repository
If any of these conditions cannot be fulfilled for any reason, unfortunately, Giscus cannot be integrated.
Configuring Giscus
Next, configuring Giscus is necessary. In most cases, the preselected defaults are suitable, and you should only modify them if you have a specific reason and know what you are doing. Don’t worry too much about making the wrong choices; you can always adjust the configuration later on.
However you need to
- select the right language for the UI
- specify the GitHub repository you want to connect, typically the repository containing your statically hosted AstroPaper blog on GitHub Pages
- create and set an
Announcementtype discussion on GitHub if you want to ensure nobody can create random comments directly on GitHub - define the color scheme
After configuring the settings, Giscus provides you with a generated <script> tag, which you will need in the next steps.
Simple script tag
You should now have a script tag that looks like this:
<script
src="https://giscus.app/client.js"
data-repo="[ENTER REPO HERE]"
data-repo-id="[ENTER REPO ID HERE]"
data-category="[ENTER CATEGORY NAME HERE]"
data-category-id="[ENTER CATEGORY ID HERE]"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="en"
crossorigin="anonymous"
async
></script>
Simply add that to the source code of the site. Most likely, if you’re using AstroPaper and want to enable comments on posts, navigate to PostDetails.astro and paste it into the desired location where you want the comments to appear, perhaps underneath the Share this post on: buttons.
<Layout {...layoutProps}>
<main>
<ShareLinks />
<script
src="https://giscus.app/client.js"
data-repo="[ENTER REPO HERE]"
data-repo-id="[ENTER REPO ID HERE]"
data-category="[ENTER CATEGORY NAME HERE]"
data-category-id="[ENTER CATEGORY ID HERE]"></script>
</main>
<Footer />
</Layout>src/layouts/PostDetails.astro
And it’s done! You have successfully integrated comments in AstroPaper!
React component with light/dark theme
The embedded script tag in the layout is quite static, with the Giscus configuration, including theme, hardcoded into the layout. Given that AstroPaper features a light/dark theme toggle, it would be nice for the comments to seamlessly transition between light and dark themes along with the rest of the site. To achieve this, a more sophisticated approach to embedding Giscus is required.
Firstly, we are going to install the React component for Giscus:
npm i @giscus/react && npx astro add react
Then we create a new Comments.tsx React component in src/components:
import Giscus, { type Theme } from "@giscus/react";
import { GISCUS } from "@/constants";
import { useEffect, useState } from "react";
interface CommentsProps {
lightTheme?: Theme;
darkTheme?: Theme;
}
export default function Comments({
lightTheme = "light",
darkTheme = "dark",
}: CommentsProps) {
const [theme, setTheme] = useState(() => {
const currentTheme = localStorage.getItem("theme");
const browserTheme = window.matchMedia("(prefers-color-scheme: dark)")
.matches
? "dark"
: "light";
return currentTheme || browserTheme;
});
useEffect(() => {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleChange = ({ matches }: MediaQueryListEvent) => {
setTheme(matches ? "dark" : "light");
};
mediaQuery.addEventListener("change", handleChange);
return () => mediaQuery.removeEventListener("change", handleChange);
}, []);
useEffect(() => {
const themeButton = document.querySelector("#theme-btn");
const handleClick = () => {
setTheme(prevTheme => (prevTheme === "dark" ? "light" : "dark"));
};
themeButton?.addEventListener("click", handleClick);
return () => themeButton?.removeEventListener("click", handleClick);
}, []);
return (
<div className="mt-8">
<Giscus theme={theme === "light" ? lightTheme : darkTheme} {...GISCUS} />
</div>
);
}src/components/Comments.tsx
This React component not only wraps the native Giscus component, but also introduces additional props, namely lightTheme and darkTheme. Leveraging two event listeners, the Giscus comments will align with the site’s theme, dynamically switching between dark and light themes whenever the site or browser theme is changed.
We also need to define the GISCUS config, for which the optimal location is in constants.ts:
import type { GiscusProps } from "@giscus/react";
...
export const GISCUS: GiscusProps = {
repo: "[ENTER REPO HERE]",
repoId: "[ENTER REPO ID HERE]",
category: "[ENTER CATEGORY NAME HERE]",
categoryId: "[ENTER CATEGORY ID HERE]",
mapping: "pathname",
reactionsEnabled: "0",
emitMetadata: "0",
inputPosition: "bottom",
lang: "en",
loading: "lazy",
};src/constants.ts
Note that specifying a theme here will override the lightTheme and darkTheme props, resulting in a static theme setting, similar to the previous approach of embedding Giscus with the <script> tag.
To complete the process, add the new Comments component to PostDetails.astro (replacing the script tag from the previous step).
import Comments from "@/components/Comments";
<ShareLinks />
<Comments client:only="react" />
<hr class="my-6 border-dashed" />
<Footer />src/layouts/PostDetails.astro
And that’s it!