<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog on 0AndWild_log</title><link>https://0andwild.com/en/series/blog/</link><description>Recent content in Blog on 0AndWild_log</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Fri, 17 Oct 2025 12:00:00 +0900</lastBuildDate><atom:link href="https://0andwild.com/en/series/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>Adding Comments to Hugo Blog with Giscus</title><link>https://0andwild.com/en/posts/251017_comments_giscus/</link><pubDate>Fri, 17 Oct 2025 12:00:00 +0900</pubDate><guid>https://0andwild.com/en/posts/251017_comments_giscus/</guid><description>&lt;img src="https://0andwild.com/" alt="Featured image of post Adding Comments to Hugo Blog with Giscus" /&gt;&lt;h2 id="what-is-giscus"&gt;&lt;a href="#what-is-giscus" class="header-anchor"&gt;&lt;/a&gt;What is Giscus?
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Giscus&lt;/strong&gt; is an open-source comment system that uses GitHub Discussions as its backend.&lt;/p&gt;
&lt;h3 id="key-features"&gt;&lt;a href="#key-features" class="header-anchor"&gt;&lt;/a&gt;Key Features
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Completely Free&lt;/strong&gt; (leverages GitHub features)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No Server Required&lt;/strong&gt; (GitHub handles everything)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Full Markdown Support&lt;/strong&gt; (code blocks, images, tables, etc.)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Reactions&lt;/strong&gt; (👍, ❤️, 😄, etc.)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;GitHub Notifications&lt;/strong&gt; (get notified when comments are posted)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Dark Mode&lt;/strong&gt; (auto-syncs with blog theme)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Data Ownership&lt;/strong&gt; (stored in your repository)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="differences-from-utterances"&gt;&lt;a href="#differences-from-utterances" class="header-anchor"&gt;&lt;/a&gt;Differences from Utterances
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th&gt;Giscus&lt;/th&gt;
					&lt;th&gt;Utterances&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Backend&lt;/td&gt;
					&lt;td&gt;GitHub Discussions&lt;/td&gt;
					&lt;td&gt;GitHub Issues&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Reactions&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nested Replies&lt;/td&gt;
					&lt;td&gt;✅ (nested)&lt;/td&gt;
					&lt;td&gt;⚠️ (flat)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Comment Sorting&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Best For&lt;/td&gt;
					&lt;td&gt;Comments&lt;/td&gt;
					&lt;td&gt;Issue tracking&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: Giscus is the superior choice over Utterances.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="prerequisites"&gt;&lt;a href="#prerequisites" class="header-anchor"&gt;&lt;/a&gt;Prerequisites
&lt;/h2&gt;&lt;h3 id="requirements"&gt;&lt;a href="#requirements" class="header-anchor"&gt;&lt;/a&gt;Requirements
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;GitHub account&lt;/li&gt;
&lt;li&gt;Public GitHub repository (your blog repository)&lt;/li&gt;
&lt;li&gt;Hugo + Blowfish theme&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="limitations"&gt;&lt;a href="#limitations" class="header-anchor"&gt;&lt;/a&gt;Limitations
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Public repositories only&lt;/strong&gt; (Private repositories have limited Discussions functionality)&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;GitHub account required&lt;/strong&gt; (no anonymous comments)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="step-1-enable-github-discussions"&gt;&lt;a href="#step-1-enable-github-discussions" class="header-anchor"&gt;&lt;/a&gt;Step 1: Enable GitHub Discussions
&lt;/h2&gt;&lt;h3 id="11-navigate-to-repository-settings"&gt;&lt;a href="#11-navigate-to-repository-settings" class="header-anchor"&gt;&lt;/a&gt;1.1 Navigate to Repository Settings
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Go to your blog repository on GitHub&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Example: https://github.com/0AndWild/0AndWild.github.io
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click the &lt;strong&gt;Settings&lt;/strong&gt; tab&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="12-enable-discussions"&gt;&lt;a href="#12-enable-discussions" class="header-anchor"&gt;&lt;/a&gt;1.2 Enable Discussions
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Scroll down to find the &lt;strong&gt;Features&lt;/strong&gt; section&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check the &lt;strong&gt;Discussions&lt;/strong&gt; checkbox ✅&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It will save automatically&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="13-verify"&gt;&lt;a href="#13-verify" class="header-anchor"&gt;&lt;/a&gt;1.3 Verify
&lt;/h3&gt;&lt;p&gt;Confirm that the &lt;strong&gt;Discussions&lt;/strong&gt; tab appears at the top of your repository&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Code | Issues | Pull requests | Discussions | ← Newly created!
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="step-2-install-giscus-app"&gt;&lt;a href="#step-2-install-giscus-app" class="header-anchor"&gt;&lt;/a&gt;Step 2: Install Giscus App
&lt;/h2&gt;&lt;h3 id="21-install-giscus-github-app"&gt;&lt;a href="#21-install-giscus-github-app" class="header-anchor"&gt;&lt;/a&gt;2.1 Install Giscus GitHub App
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Visit &lt;a class="link" href="https://github.com/apps/giscus" target="_blank" rel="noopener"
 &gt;https://github.com/apps/giscus&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click the &lt;strong&gt;Install&lt;/strong&gt; button&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Choose permission scope:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;All repositories&lt;/strong&gt; (all repositories)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Only select repositories&lt;/strong&gt; (specific repositories - recommended)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select your blog repository:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;0AndWild/0AndWild.github.io
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="22-verify-permissions"&gt;&lt;a href="#22-verify-permissions" class="header-anchor"&gt;&lt;/a&gt;2.2 Verify Permissions
&lt;/h3&gt;&lt;p&gt;Giscus requests the following permissions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Read access to discussions&lt;/strong&gt; (read discussions)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Write access to discussions&lt;/strong&gt; (write discussions)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Read access to metadata&lt;/strong&gt; (read metadata)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="step-3-generate-giscus-configuration"&gt;&lt;a href="#step-3-generate-giscus-configuration" class="header-anchor"&gt;&lt;/a&gt;Step 3: Generate Giscus Configuration
&lt;/h2&gt;&lt;h3 id="31-visit-giscus-website"&gt;&lt;a href="#31-visit-giscus-website" class="header-anchor"&gt;&lt;/a&gt;3.1 Visit Giscus Website
&lt;/h3&gt;&lt;p&gt;Go to &lt;a class="link" href="https://giscus.app" target="_blank" rel="noopener"
 &gt;https://giscus.app&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="32-connect-repository"&gt;&lt;a href="#32-connect-repository" class="header-anchor"&gt;&lt;/a&gt;3.2 Connect Repository
&lt;/h3&gt;&lt;p&gt;Enter in the &lt;strong&gt;Repository&lt;/strong&gt; section:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;0AndWild/0AndWild.github.io
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see a success message below:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;✅ Success! This repository meets all criteria.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you see an error:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Verify Discussions is enabled&lt;/li&gt;
&lt;li&gt;Verify Giscus App is installed&lt;/li&gt;
&lt;li&gt;Verify the repository is Public&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="33-page--discussion-mapping"&gt;&lt;a href="#33-page--discussion-mapping" class="header-anchor"&gt;&lt;/a&gt;3.3 Page ↔️ Discussion Mapping
&lt;/h3&gt;&lt;p&gt;Choose in the &lt;strong&gt;Discussion Mapping&lt;/strong&gt; section:&lt;/p&gt;
&lt;h4 id="recommended-pathname-path-name"&gt;&lt;a href="#recommended-pathname-path-name" class="header-anchor"&gt;&lt;/a&gt;Recommended: &lt;code&gt;pathname&lt;/code&gt; (path name)
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Mapping: Select pathname
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each blog post&amp;rsquo;s path becomes the Discussion title.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Post: &lt;code&gt;/posts/giscus-guide/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Discussion title: &lt;code&gt;posts/giscus-guide&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="alternatives"&gt;&lt;a href="#alternatives" class="header-anchor"&gt;&lt;/a&gt;Alternatives:
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;URL&lt;/code&gt;: Uses full URL (problematic if domain changes)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt;: Uses post title (problematic if title changes)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;og:title&lt;/code&gt;: OpenGraph title&lt;/li&gt;
&lt;li&gt;&lt;code&gt;specific term&lt;/code&gt;: Manually specified&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;: Use &lt;code&gt;pathname&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="34-select-discussion-category"&gt;&lt;a href="#34-select-discussion-category" class="header-anchor"&gt;&lt;/a&gt;3.4 Select Discussion Category
&lt;/h3&gt;&lt;p&gt;Choose from the &lt;strong&gt;Discussion Category&lt;/strong&gt; dropdown:&lt;/p&gt;
&lt;h4 id="recommended-announcements"&gt;&lt;a href="#recommended-announcements" class="header-anchor"&gt;&lt;/a&gt;Recommended: &lt;code&gt;Announcements&lt;/code&gt;
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Category: Select Announcements
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Characteristics&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only admins can create new Discussions&lt;/li&gt;
&lt;li&gt;Anyone can comment&lt;/li&gt;
&lt;li&gt;Ideal for blog posts&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="alternative-general"&gt;&lt;a href="#alternative-general" class="header-anchor"&gt;&lt;/a&gt;Alternative: &lt;code&gt;General&lt;/code&gt;
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Anyone can create Discussions&lt;/li&gt;
&lt;li&gt;More open&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;: &lt;code&gt;Announcements&lt;/code&gt; (best for blogs)&lt;/p&gt;
&lt;h3 id="35-feature-selection"&gt;&lt;a href="#35-feature-selection" class="header-anchor"&gt;&lt;/a&gt;3.5 Feature Selection
&lt;/h3&gt;&lt;h4 id="enable-reactions"&gt;&lt;a href="#enable-reactions" class="header-anchor"&gt;&lt;/a&gt;Enable Reactions
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;✅ Enable reactions
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Users can react with 👍, ❤️, 😄, etc.&lt;/p&gt;
&lt;h4 id="emit-metadata"&gt;&lt;a href="#emit-metadata" class="header-anchor"&gt;&lt;/a&gt;Emit Metadata
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;□ Emit metadata (recommended to leave unchecked)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unnecessary feature, better to keep it off&lt;/p&gt;
&lt;h4 id="comment-input-position"&gt;&lt;a href="#comment-input-position" class="header-anchor"&gt;&lt;/a&gt;Comment Input Position
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;⚪ Above comments
⚪ Below comments (recommended)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;: Below comments&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encourages users to read existing comments first&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="lazy-loading"&gt;&lt;a href="#lazy-loading" class="header-anchor"&gt;&lt;/a&gt;Lazy Loading
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;✅ Lazy loading
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Improves page load speed (recommended)&lt;/p&gt;
&lt;h3 id="36-theme-selection"&gt;&lt;a href="#36-theme-selection" class="header-anchor"&gt;&lt;/a&gt;3.6 Theme Selection
&lt;/h3&gt;&lt;h4 id="recommended-preferred_color_scheme"&gt;&lt;a href="#recommended-preferred_color_scheme" class="header-anchor"&gt;&lt;/a&gt;Recommended: &lt;code&gt;preferred_color_scheme&lt;/code&gt;
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Theme: preferred_color_scheme
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Behavior&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatically switches based on user&amp;rsquo;s system settings&lt;/li&gt;
&lt;li&gt;Dark mode ↔️ Light mode automatic&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="alternatives-1"&gt;&lt;a href="#alternatives-1" class="header-anchor"&gt;&lt;/a&gt;Alternatives:
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;light&lt;/code&gt;: Always light theme&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dark&lt;/code&gt;: Always dark theme&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transparent_dark&lt;/code&gt;: Transparent dark&lt;/li&gt;
&lt;li&gt;Other GitHub themes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;: &lt;code&gt;preferred_color_scheme&lt;/code&gt; (auto-switching)&lt;/p&gt;
&lt;h3 id="37-language-setting"&gt;&lt;a href="#37-language-setting" class="header-anchor"&gt;&lt;/a&gt;3.7 Language Setting
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;Language: en (English)
&lt;/code&gt;&lt;/pre&gt;&lt;hr&gt;
&lt;h2 id="step-4-copy-generated-code"&gt;&lt;a href="#step-4-copy-generated-code" class="header-anchor"&gt;&lt;/a&gt;Step 4: Copy Generated Code
&lt;/h2&gt;&lt;h3 id="41-copy-script"&gt;&lt;a href="#41-copy-script" class="header-anchor"&gt;&lt;/a&gt;4.1 Copy Script
&lt;/h3&gt;&lt;p&gt;Copy the generated code from the &lt;strong&gt;Enable giscus&lt;/strong&gt; section at the bottom of the page:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0AndWild/0AndWild.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;R_kgDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Announcements&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DIC_kwDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-reactions-enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-emit-metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-input-position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;preferred_color_scheme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="42-important-values"&gt;&lt;a href="#42-important-values" class="header-anchor"&gt;&lt;/a&gt;4.2 Important Values
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;data-repo-id&lt;/code&gt;: Repository unique ID (auto-generated)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data-category-id&lt;/code&gt;: Category unique ID (auto-generated)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These values are unique to your repository, so you must use the code generated from the Giscus website.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="step-5-integrate-with-blowfish-theme"&gt;&lt;a href="#step-5-integrate-with-blowfish-theme" class="header-anchor"&gt;&lt;/a&gt;Step 5: Integrate with Blowfish Theme
&lt;/h2&gt;&lt;h3 id="51-create-directory"&gt;&lt;a href="#51-create-directory" class="header-anchor"&gt;&lt;/a&gt;5.1 Create Directory
&lt;/h3&gt;&lt;p&gt;From the terminal, navigate to your blog&amp;rsquo;s root directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p layouts/partials
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="52-create-commentshtml-file"&gt;&lt;a href="#52-create-commentshtml-file" class="header-anchor"&gt;&lt;/a&gt;5.2 Create comments.html File
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;touch layouts/partials/comments.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or create directly in your IDE/editor:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;layouts/
 └── partials/
 └── comments.html ← Create new
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="53-insert-giscus-code"&gt;&lt;a href="#53-insert-giscus-code" class="header-anchor"&gt;&lt;/a&gt;5.3 Insert Giscus Code
&lt;/h3&gt;&lt;p&gt;Add the following content to &lt;code&gt;layouts/partials/comments.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Giscus Comment System --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0AndWild/0AndWild.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;R_kgDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Announcements&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DIC_kwDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-reactions-enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-emit-metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-input-position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;preferred_color_scheme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-loading&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;lazy&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;⚠️ &lt;strong&gt;Important&lt;/strong&gt;: Replace the &lt;code&gt;data-repo-id&lt;/code&gt; and &lt;code&gt;data-category-id&lt;/code&gt; values with &lt;strong&gt;your own values&lt;/strong&gt;!&lt;/p&gt;
&lt;h3 id="54-configure-paramstoml"&gt;&lt;a href="#54-configure-paramstoml" class="header-anchor"&gt;&lt;/a&gt;5.4 Configure params.toml
&lt;/h3&gt;&lt;p&gt;Open &lt;code&gt;config/_default/params.toml&lt;/code&gt; and add to the &lt;code&gt;[article]&lt;/code&gt; section:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# Add or verify this line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# ... other settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the &lt;code&gt;showComments&lt;/code&gt; entry already exists, make sure it&amp;rsquo;s set to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="step-6-local-testing"&gt;&lt;a href="#step-6-local-testing" class="header-anchor"&gt;&lt;/a&gt;Step 6: Local Testing
&lt;/h2&gt;&lt;h3 id="61-run-hugo-server"&gt;&lt;a href="#61-run-hugo-server" class="header-anchor"&gt;&lt;/a&gt;6.1 Run Hugo Server
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="62-verify-in-browser"&gt;&lt;a href="#62-verify-in-browser" class="header-anchor"&gt;&lt;/a&gt;6.2 Verify in Browser
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;http://localhost:1313
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The Giscus comment widget should appear at the bottom of post pages.&lt;/p&gt;
&lt;h3 id="63-write-test-comment"&gt;&lt;a href="#63-write-test-comment" class="header-anchor"&gt;&lt;/a&gt;6.3 Write Test Comment
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Sign in with GitHub&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Authorize GitHub OAuth&lt;/li&gt;
&lt;li&gt;Write a test comment&lt;/li&gt;
&lt;li&gt;Verify the comment displays&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="64-check-github-discussions"&gt;&lt;a href="#64-check-github-discussions" class="header-anchor"&gt;&lt;/a&gt;6.4 Check GitHub Discussions
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;GitHub repository → &lt;strong&gt;Discussions&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Verify a new Discussion was created in the Announcements category&lt;/li&gt;
&lt;li&gt;Verify the Discussion title matches the post path&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="step-7-deploy"&gt;&lt;a href="#step-7-deploy" class="header-anchor"&gt;&lt;/a&gt;Step 7: Deploy
&lt;/h2&gt;&lt;h3 id="71-commit-to-git"&gt;&lt;a href="#71-commit-to-git" class="header-anchor"&gt;&lt;/a&gt;7.1 Commit to Git
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add layouts/partials/comments.html
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add config/_default/params.toml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;Add Giscus comments system&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="72-push-to-github"&gt;&lt;a href="#72-push-to-github" class="header-anchor"&gt;&lt;/a&gt;7.2 Push to GitHub
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push origin main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="73-check-github-actions"&gt;&lt;a href="#73-check-github-actions" class="header-anchor"&gt;&lt;/a&gt;7.3 Check GitHub Actions
&lt;/h3&gt;&lt;p&gt;GitHub Actions will automatically build and deploy.&lt;/p&gt;
&lt;p&gt;Check deployment status:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;GitHub repository → Actions tab
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="74-verify-deployed-site"&gt;&lt;a href="#74-verify-deployed-site" class="header-anchor"&gt;&lt;/a&gt;7.4 Verify Deployed Site
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;https://0andwild.github.io
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Verify the comment widget displays correctly on post pages.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="advanced-configuration"&gt;&lt;a href="#advanced-configuration" class="header-anchor"&gt;&lt;/a&gt;Advanced Configuration
&lt;/h2&gt;&lt;h3 id="dynamic-dark-mode-and-language-setting-recommended"&gt;&lt;a href="#dynamic-dark-mode-and-language-setting-recommended" class="header-anchor"&gt;&lt;/a&gt;Dynamic Dark Mode and Language Setting (Recommended)
&lt;/h3&gt;&lt;p&gt;A complete solution to make Giscus automatically adapt to Blowfish theme&amp;rsquo;s dark mode toggle and language switching.&lt;/p&gt;
&lt;h4 id="complete-dynamic-configuration"&gt;&lt;a href="#complete-dynamic-configuration" class="header-anchor"&gt;&lt;/a&gt;Complete Dynamic Configuration
&lt;/h4&gt;&lt;p&gt;Full code for &lt;code&gt;layouts/partials/comments.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Giscus Comments with Dynamic Theme and Language --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{ $lang := .Site.Language.Lang }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{{ $translationKey := .File.TranslationBaseName }}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Get current theme (dark/light)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark_tritanopia&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light_tritanopia&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Get language from Hugo template
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentLang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{{ $lang }}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Use file directory path for unified comments across languages
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Example: &amp;#34;posts/subscription_alert&amp;#34; for both index.ko.md and index.en.md
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discussionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;{{ .File.Dir | replaceRE &amp;#34;^content/&amp;#34; &amp;#34;&amp;#34; | replaceRE &amp;#34;/$&amp;#34; &amp;#34;&amp;#34; }}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Wait for DOM to be ready
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;loading&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;DOMContentLoaded&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initGiscus&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;initGiscus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;initGiscus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create and insert Giscus script with dynamic settings
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://giscus.app/client.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-repo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0AndWild/0AndWild.github.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-repo-id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;R_kgDOQAqZFA&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-category&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;General&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-category-id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;DIC_kwDOQAqZFM4CwwRg&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-mapping&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;specific&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-term&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discussionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-strict&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-reactions-enabled&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-emit-metadata&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-input-position&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bottom&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-theme&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-lang&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentLang&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-loading&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;lazy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;crossorigin&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;anonymous&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Find giscus container or create one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.giscus-container&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentScript&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parentElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Monitor theme changes and update Giscus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;updateGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;iframe.giscus-frame&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;giscus&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setConfig&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;https://giscus.app&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Giscus theme update delayed, will retry...&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Watch for theme changes using MutationObserver
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributeName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Delay update to ensure iframe is ready
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Start observing after a short delay
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;attributeFilter&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Update theme when Giscus iframe loads
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://giscus.app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;giscus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Giscus is ready, update theme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Ensure Giscus iframe has proper height and displays all content */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;giscus-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;giscus-container&lt;/span&gt; &lt;span class="nt"&gt;iframe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;giscus-frame&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="kt"&gt;%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;/* Make sure comment actions are visible */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;giscus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;visible&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;giscus-container&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="how-it-works"&gt;&lt;a href="#how-it-works" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h4&gt;&lt;h5 id="1-dynamic-language-setting"&gt;&lt;a href="#1-dynamic-language-setting" class="header-anchor"&gt;&lt;/a&gt;1. &lt;strong&gt;Dynamic Language Setting&lt;/strong&gt;
&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Language&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Lang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentLang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Gets current page language from Hugo template&lt;/li&gt;
&lt;li&gt;Korean page: &lt;code&gt;ko&lt;/code&gt;, English page: &lt;code&gt;en&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sets Giscus to the corresponding language&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Korean page → Giscus UI displays in Korean&lt;/li&gt;
&lt;li&gt;English page → Giscus UI displays in English&lt;/li&gt;
&lt;li&gt;Language switch triggers page reload with automatic update&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="2-dynamic-dark-mode-setting"&gt;&lt;a href="#2-dynamic-dark-mode-setting" class="header-anchor"&gt;&lt;/a&gt;2. &lt;strong&gt;Dynamic Dark Mode Setting&lt;/strong&gt;
&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark_tritanopia&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light_tritanopia&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Blowfish theme adds &lt;code&gt;&amp;lt;html class=&amp;quot;dark&amp;quot;&amp;gt;&lt;/code&gt; in dark mode&lt;/li&gt;
&lt;li&gt;Detects this to determine theme&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;dark_tritanopia&lt;/code&gt; / &lt;code&gt;light_tritanopia&lt;/code&gt; themes (colorblind-friendly)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Page load: Loads Giscus with current theme state&lt;/li&gt;
&lt;li&gt;Dark mode toggle click: Real-time Giscus theme change&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="3-unified-comments-across-languages"&gt;&lt;a href="#3-unified-comments-across-languages" class="header-anchor"&gt;&lt;/a&gt;3. &lt;strong&gt;Unified Comments Across Languages&lt;/strong&gt;
&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;discussionId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Dir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;replaceRE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;^content/&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;replaceRE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/$&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Uses file directory path as Discussion ID&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content/posts/subscription_alert/index.ko.md&lt;/code&gt; → &lt;code&gt;posts/subscription_alert&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content/posts/subscription_alert/index.en.md&lt;/code&gt; → &lt;code&gt;posts/subscription_alert&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Same ID means Korean/English versions share the same comments&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Comments written on Korean post&lt;/li&gt;
&lt;li&gt;Also display on English post&lt;/li&gt;
&lt;li&gt;Separate Discussions created per post&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id="4-real-time-theme-change-detection"&gt;&lt;a href="#4-real-time-theme-change-detection" class="header-anchor"&gt;&lt;/a&gt;4. &lt;strong&gt;Real-time Theme Change Detection&lt;/strong&gt;
&lt;/h5&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MutationObserver&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;mutations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mutation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributeName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;class&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MutationObserver&lt;/code&gt; detects HTML class changes&lt;/li&gt;
&lt;li&gt;Immediately detects dark mode toggle clicks&lt;/li&gt;
&lt;li&gt;Sends theme change command to Giscus iframe via &lt;code&gt;postMessage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="testing-method"&gt;&lt;a href="#testing-method" class="header-anchor"&gt;&lt;/a&gt;Testing Method
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. Run local server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. Verify in browser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;http://localhost:1313/posts/subscription_alert/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Test Items&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;✅ Page load displays Giscus with current theme (light/dark)&lt;/li&gt;
&lt;li&gt;✅ Dark mode toggle click immediately changes Giscus theme&lt;/li&gt;
&lt;li&gt;✅ Language switch (ko → en) changes Giscus language&lt;/li&gt;
&lt;li&gt;✅ Korean/English pages display same comments&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="changing-theme-options"&gt;&lt;a href="#changing-theme-options" class="header-anchor"&gt;&lt;/a&gt;Changing Theme Options
&lt;/h4&gt;&lt;p&gt;To use different themes, modify the &lt;code&gt;getGiscusTheme()&lt;/code&gt; function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Basic theme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// High contrast theme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark_high_contrast&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light_high_contrast&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// GitHub style theme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getGiscusTheme&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;isDark&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark_dimmed&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Available themes&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;light&lt;/code&gt; / &lt;code&gt;dark&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;light_high_contrast&lt;/code&gt; / &lt;code&gt;dark_high_contrast&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;light_tritanopia&lt;/code&gt; / &lt;code&gt;dark_tritanopia&lt;/code&gt; (colorblind-friendly)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dark_dimmed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transparent_dark&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preferred_color_scheme&lt;/code&gt; (follows system settings)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="static-theme-configuration-simple-method"&gt;&lt;a href="#static-theme-configuration-simple-method" class="header-anchor"&gt;&lt;/a&gt;Static Theme Configuration (Simple Method)
&lt;/h4&gt;&lt;p&gt;If dynamic changes aren&amp;rsquo;t needed, you can configure statically:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0AndWild/0AndWild.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;R_kgDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;General&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DIC_kwDOxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;preferred_color_scheme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: Simple
&lt;strong&gt;Cons&lt;/strong&gt;: No real-time theme changes, comments separated by language&lt;/p&gt;
&lt;h3 id="hide-comments-on-specific-posts"&gt;&lt;a href="#hide-comments-on-specific-posts" class="header-anchor"&gt;&lt;/a&gt;Hide Comments on Specific Posts
&lt;/h3&gt;&lt;p&gt;To hide comments on specific posts only, add to that post&amp;rsquo;s front matter:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Post Without Comments&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;showComments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Hide comments on this post only&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="separate-comments-by-category"&gt;&lt;a href="#separate-comments-by-category" class="header-anchor"&gt;&lt;/a&gt;Separate Comments by Category
&lt;/h3&gt;&lt;p&gt;To use different Discussion categories for posts in different categories:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Conditional category configuration --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;categories&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Tutorial&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DIC_kwDOxxxxTutorial&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;DIC_kwDOxxxxGeneral&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="p"&gt;}};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ category }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="troubleshooting"&gt;&lt;a href="#troubleshooting" class="header-anchor"&gt;&lt;/a&gt;Troubleshooting
&lt;/h2&gt;&lt;h3 id="comment-widget-not-displaying"&gt;&lt;a href="#comment-widget-not-displaying" class="header-anchor"&gt;&lt;/a&gt;Comment Widget Not Displaying
&lt;/h3&gt;&lt;h4 id="cause-1-discussions-not-enabled"&gt;&lt;a href="#cause-1-discussions-not-enabled" class="header-anchor"&gt;&lt;/a&gt;Cause 1: Discussions Not Enabled
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Solution: GitHub repository → Settings → Check Discussions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="cause-2-giscus-app-not-installed"&gt;&lt;a href="#cause-2-giscus-app-not-installed" class="header-anchor"&gt;&lt;/a&gt;Cause 2: Giscus App Not Installed
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Solution: Install at https://github.com/apps/giscus
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="cause-3-repository-id-error"&gt;&lt;a href="#cause-3-repository-id-error" class="header-anchor"&gt;&lt;/a&gt;Cause 3: Repository ID Error
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Solution: Regenerate code at giscus.app
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="cause-4-showcomments-setting-missing"&gt;&lt;a href="#cause-4-showcomments-setting-missing" class="header-anchor"&gt;&lt;/a&gt;Cause 4: showComments Setting Missing
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# config/_default/params.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c"&gt;# Verify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="only-login-button-shows-cant-comment"&gt;&lt;a href="#only-login-button-shows-cant-comment" class="header-anchor"&gt;&lt;/a&gt;Only Login Button Shows, Can&amp;rsquo;t Comment
&lt;/h3&gt;&lt;h4 id="cause-github-oauth-authorization-needed"&gt;&lt;a href="#cause-github-oauth-authorization-needed" class="header-anchor"&gt;&lt;/a&gt;Cause: GitHub OAuth Authorization Needed
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Click &lt;span class="s2"&gt;&amp;#34;Sign in with GitHub&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Authorize OAuth permissions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Redirect to repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Can write comments
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="comments-not-saving"&gt;&lt;a href="#comments-not-saving" class="header-anchor"&gt;&lt;/a&gt;Comments Not Saving
&lt;/h3&gt;&lt;h4 id="cause-repository-permission-issue"&gt;&lt;a href="#cause-repository-permission-issue" class="header-anchor"&gt;&lt;/a&gt;Cause: Repository Permission Issue
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Check:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Is the repository Public?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Is the repository included in Giscus App permissions?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Does the Discussion category exist?
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="dark-mode-not-syncing"&gt;&lt;a href="#dark-mode-not-syncing" class="header-anchor"&gt;&lt;/a&gt;Dark Mode Not Syncing
&lt;/h3&gt;&lt;h4 id="solution-add-javascript-sync-code"&gt;&lt;a href="#solution-add-javascript-sync-code" class="header-anchor"&gt;&lt;/a&gt;Solution: Add JavaScript Sync Code
&lt;/h4&gt;&lt;p&gt;Refer to &amp;ldquo;Advanced Configuration &amp;gt; Automatic Dark Mode Switching&amp;rdquo; above&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="managing-giscus"&gt;&lt;a href="#managing-giscus" class="header-anchor"&gt;&lt;/a&gt;Managing Giscus
&lt;/h2&gt;&lt;h3 id="comment-management"&gt;&lt;a href="#comment-management" class="header-anchor"&gt;&lt;/a&gt;Comment Management
&lt;/h3&gt;&lt;h4 id="manage-via-github-discussions"&gt;&lt;a href="#manage-via-github-discussions" class="header-anchor"&gt;&lt;/a&gt;Manage via GitHub Discussions
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. GitHub repository → Discussions tab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Click the relevant Discussion
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Management actions:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Edit comment &lt;span class="o"&gt;(&lt;/span&gt;own comments only&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Delete comment &lt;span class="o"&gt;(&lt;/span&gt;admin&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Block user &lt;span class="o"&gt;(&lt;/span&gt;admin&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Lock Discussion &lt;span class="o"&gt;(&lt;/span&gt;admin&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="handling-spam-comments"&gt;&lt;a href="#handling-spam-comments" class="header-anchor"&gt;&lt;/a&gt;Handling Spam Comments
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Find spam comment in GitHub Discussions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. ... menu next to comment → &lt;span class="s2"&gt;&amp;#34;Delete&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Block user: Profile → Block user
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="notification-settings"&gt;&lt;a href="#notification-settings" class="header-anchor"&gt;&lt;/a&gt;Notification Settings
&lt;/h3&gt;&lt;h4 id="receive-comment-notifications-via-github"&gt;&lt;a href="#receive-comment-notifications-via-github" class="header-anchor"&gt;&lt;/a&gt;Receive Comment Notifications via GitHub
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. GitHub → Settings → Notifications
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Add repository to Watching
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Configure email notifications
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="receive-notifications-for-specific-discussions-only"&gt;&lt;a href="#receive-notifications-for-specific-discussions-only" class="header-anchor"&gt;&lt;/a&gt;Receive Notifications for Specific Discussions Only
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Discussions tab → Relevant Discussion
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. &lt;span class="s2"&gt;&amp;#34;Subscribe&amp;#34;&lt;/span&gt; button on right
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Select &lt;span class="s2"&gt;&amp;#34;Notify me&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="statistics-and-analytics"&gt;&lt;a href="#statistics-and-analytics" class="header-anchor"&gt;&lt;/a&gt;Statistics and Analytics
&lt;/h2&gt;&lt;h3 id="view-comment-statistics"&gt;&lt;a href="#view-comment-statistics" class="header-anchor"&gt;&lt;/a&gt;View Comment Statistics
&lt;/h3&gt;&lt;p&gt;In GitHub Discussions:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Discussions tab
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Check number of Discussions by category
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Check comment count &lt;span class="k"&gt;for&lt;/span&gt; each Discussion
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="utilize-github-insights"&gt;&lt;a href="#utilize-github-insights" class="header-anchor"&gt;&lt;/a&gt;Utilize GitHub Insights
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GitHub repository → Insights → Community
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ Check Discussions activity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="cost-and-limitations"&gt;&lt;a href="#cost-and-limitations" class="header-anchor"&gt;&lt;/a&gt;Cost and Limitations
&lt;/h2&gt;&lt;h3 id="cost"&gt;&lt;a href="#cost" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Completely Free&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only need a GitHub account&lt;/li&gt;
&lt;li&gt;Unlimited comments within repository size limits&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="limitations-1"&gt;&lt;a href="#limitations-1" class="header-anchor"&gt;&lt;/a&gt;Limitations
&lt;/h3&gt;&lt;h4 id="github-api-rate-limit"&gt;&lt;a href="#github-api-rate-limit" class="header-anchor"&gt;&lt;/a&gt;GitHub API Rate Limit
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;60 requests/hour (unauthenticated)&lt;/li&gt;
&lt;li&gt;5,000 requests/hour (authenticated)&lt;/li&gt;
&lt;li&gt;Giscus is optimized with caching, so no issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="repository-size"&gt;&lt;a href="#repository-size" class="header-anchor"&gt;&lt;/a&gt;Repository Size
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;GitHub Free: 1GB per repository&lt;/li&gt;
&lt;li&gt;Text comments alone won&amp;rsquo;t reach the limit&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="discussions-limit"&gt;&lt;a href="#discussions-limit" class="header-anchor"&gt;&lt;/a&gt;Discussions Limit
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;None (unlimited)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="alternative-comparisons"&gt;&lt;a href="#alternative-comparisons" class="header-anchor"&gt;&lt;/a&gt;Alternative Comparisons
&lt;/h2&gt;&lt;h3 id="giscus-vs-utterances"&gt;&lt;a href="#giscus-vs-utterances" class="header-anchor"&gt;&lt;/a&gt;Giscus vs Utterances
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;Giscus&lt;/th&gt;
					&lt;th&gt;Utterances&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Backend&lt;/td&gt;
					&lt;td&gt;Discussions&lt;/td&gt;
					&lt;td&gt;Issues&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Reactions&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nested Replies&lt;/td&gt;
					&lt;td&gt;Nested support&lt;/td&gt;
					&lt;td&gt;Flat&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Recommendation&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: Giscus is recommended&lt;/p&gt;
&lt;h3 id="giscus-vs-disqus"&gt;&lt;a href="#giscus-vs-disqus" class="header-anchor"&gt;&lt;/a&gt;Giscus vs Disqus
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;Giscus&lt;/th&gt;
					&lt;th&gt;Disqus&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Cost&lt;/td&gt;
					&lt;td&gt;Free&lt;/td&gt;
					&lt;td&gt;Free (with ads)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Ads&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Anonymous Comments&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅ (Guest)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Markdown&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Data Ownership&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Recommendation&lt;/td&gt;
					&lt;td&gt;Developer blogs&lt;/td&gt;
					&lt;td&gt;General blogs&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="migration-guide"&gt;&lt;a href="#migration-guide" class="header-anchor"&gt;&lt;/a&gt;Migration Guide
&lt;/h2&gt;&lt;h3 id="utterances--giscus"&gt;&lt;a href="#utterances--giscus" class="header-anchor"&gt;&lt;/a&gt;Utterances → Giscus
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Convert GitHub Issues to Discussions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Manual work required &lt;span class="o"&gt;(&lt;/span&gt;no automation&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Or leave Issues as-is and start fresh with Giscus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Replace comments.html file
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Delete Utterances code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Add Giscus code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Deploy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="disqus--giscus"&gt;&lt;a href="#disqus--giscus" class="header-anchor"&gt;&lt;/a&gt;Disqus → Giscus
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Export Disqus data &lt;span class="o"&gt;(&lt;/span&gt;XML&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Manual migration to GitHub Discussions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - No automation tools available
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Need to write custom script
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Or starting fresh recommended
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="additional-resources"&gt;&lt;a href="#additional-resources" class="header-anchor"&gt;&lt;/a&gt;Additional Resources
&lt;/h2&gt;&lt;h3 id="official-documentation"&gt;&lt;a href="#official-documentation" class="header-anchor"&gt;&lt;/a&gt;Official Documentation
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://giscus.app" target="_blank" rel="noopener"
 &gt;Giscus Official Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/giscus/giscus" target="_blank" rel="noopener"
 &gt;Giscus GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="community"&gt;&lt;a href="#community" class="header-anchor"&gt;&lt;/a&gt;Community
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/giscus/giscus/discussions" target="_blank" rel="noopener"
 &gt;Giscus Discussions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blowfish.page/docs/" target="_blank" rel="noopener"
 &gt;Blowfish Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="checklist"&gt;&lt;a href="#checklist" class="header-anchor"&gt;&lt;/a&gt;Checklist
&lt;/h2&gt;&lt;p&gt;Installation completion checklist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; GitHub Discussions enabled&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Giscus App installed&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Created &lt;code&gt;layouts/partials/comments.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Inserted Giscus code (with your own IDs)&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Set &lt;code&gt;showComments = true&lt;/code&gt; in &lt;code&gt;params.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Local testing complete&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Pushed to GitHub&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Verified on deployed site&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Wrote test comment&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Verified creation in GitHub Discussions&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Giscus is the most suitable comment system for Hugo/GitHub Pages blogs:&lt;/p&gt;
&lt;h3 id="summary-of-advantages"&gt;&lt;a href="#summary-of-advantages" class="header-anchor"&gt;&lt;/a&gt;Summary of Advantages
&lt;/h3&gt;&lt;p&gt;✅ Completely free
✅ Simple setup (10 minutes)
✅ No server required
✅ Full Markdown support
✅ GitHub integration
✅ Data ownership&lt;/p&gt;
&lt;h3 id="disadvantages"&gt;&lt;a href="#disadvantages" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;p&gt;❌ GitHub account required (no anonymous comments)
❌ Best for technical blogs (barrier for general users)&lt;/p&gt;
&lt;h3 id="recommended-for"&gt;&lt;a href="#recommended-for" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Developer blogs&lt;/li&gt;
&lt;li&gt;✅ Technical documentation&lt;/li&gt;
&lt;li&gt;✅ Open source projects&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Complete Guide to Comment Systems for Static Blogs</title><link>https://0andwild.com/en/posts/251017_comments_guide/</link><pubDate>Fri, 17 Oct 2025 11:00:00 +0900</pubDate><guid>https://0andwild.com/en/posts/251017_comments_guide/</guid><description>&lt;img src="https://0andwild.com/" alt="Featured image of post Complete Guide to Comment Systems for Static Blogs" /&gt;&lt;h2 id="overview"&gt;&lt;a href="#overview" class="header-anchor"&gt;&lt;/a&gt;Overview
&lt;/h2&gt;&lt;p&gt;This guide provides a comprehensive comparison of all methods to add comment functionality to blogs built with static site generators (Hugo). We present solutions for various requirements including &lt;strong&gt;anonymous comments&lt;/strong&gt;, &lt;strong&gt;GitHub login&lt;/strong&gt;, and &lt;strong&gt;social logins&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="comment-system-classification"&gt;&lt;a href="#comment-system-classification" class="header-anchor"&gt;&lt;/a&gt;Comment System Classification
&lt;/h2&gt;&lt;h3 id="by-authentication-method"&gt;&lt;a href="#by-authentication-method" class="header-anchor"&gt;&lt;/a&gt;By Authentication Method
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Authentication&lt;/th&gt;
					&lt;th&gt;Systems&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;GitHub Only&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Giscus, Utterances&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Anonymous Supported&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Remark42, Commento, Comentario, HashOver&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Anonymous + Social Login&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Remark42, Commento, Disqus&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Social Login Only&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Disqus, Hyvor Talk&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="by-hosting-method"&gt;&lt;a href="#by-hosting-method" class="header-anchor"&gt;&lt;/a&gt;By Hosting Method
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Hosting&lt;/th&gt;
					&lt;th&gt;Systems&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;SaaS (No Management)&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Giscus, Utterances, Disqus, Hyvor Talk&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Self-Hosted&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Remark42, Commento, Comentario, HashOver&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Hybrid&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Cusdis (Free Vercel deployment)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="1-giscus-highly-recommended---for-github-users"&gt;&lt;a href="#1-giscus-highly-recommended---for-github-users" class="header-anchor"&gt;&lt;/a&gt;1. Giscus (Highly Recommended - For GitHub Users)
&lt;/h2&gt;&lt;h3 id="concept"&gt;&lt;a href="#concept" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Comment system using GitHub Discussions as backend&lt;/p&gt;
&lt;h3 id="how-it-works"&gt;&lt;a href="#how-it-works" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. User visits blog
 ↓
2. Giscus widget loads
 ↓
3. Login with GitHub OAuth
 ↓
4. Write comment
 ↓
5. Auto-saved to GitHub Discussions
 ↓
6. Displayed on blog in real-time
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages"&gt;&lt;a href="#advantages" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Completely free&lt;/strong&gt; (leverages GitHub features)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No server required&lt;/strong&gt; (GitHub handles backend)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Data ownership&lt;/strong&gt; (stored in your repository)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Markdown support&lt;/strong&gt; (code blocks, images, etc.)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Reactions support&lt;/strong&gt; (👍, ❤️, etc.)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Notifications&lt;/strong&gt; (comment alerts via GitHub notifications)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Dark mode&lt;/strong&gt; (syncs with blog theme)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Spam prevention&lt;/strong&gt; (requires GitHub account)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Easy management&lt;/strong&gt; (manage in GitHub Discussions)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Searchable&lt;/strong&gt; (search comments via GitHub search)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages"&gt;&lt;a href="#disadvantages" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;No anonymous comments&lt;/strong&gt; (GitHub account required)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Best for tech blogs&lt;/strong&gt; (general users may not have GitHub accounts)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;GitHub dependency&lt;/strong&gt; (comments unavailable during GitHub outages)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty"&gt;&lt;a href="#implementation-difficulty" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐ (2/5)&lt;/p&gt;
&lt;h3 id="setup-method"&gt;&lt;a href="#setup-method" class="header-anchor"&gt;&lt;/a&gt;Setup Method
&lt;/h3&gt;&lt;h4 id="step-1-enable-github-discussions"&gt;&lt;a href="#step-1-enable-github-discussions" class="header-anchor"&gt;&lt;/a&gt;Step 1: Enable GitHub Discussions
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. GitHub Repository → Settings
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Features section → Check Discussions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-2-configure-giscus"&gt;&lt;a href="#step-2-configure-giscus" class="header-anchor"&gt;&lt;/a&gt;Step 2: Configure Giscus
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;Visit &lt;a class="link" href="https://giscus.app" target="_blank" rel="noopener"
 &gt;giscus.app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enter repository: &lt;code&gt;username/repository&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Select settings:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Page ↔️ Discussion mapping&lt;/strong&gt;: &lt;code&gt;pathname&lt;/code&gt; (recommended)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discussion category&lt;/strong&gt;: &lt;code&gt;Announcements&lt;/code&gt; or &lt;code&gt;General&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Features&lt;/strong&gt;: Reactions, comments above&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theme&lt;/strong&gt;: Match your blog theme&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="step-3-add-to-blowfish"&gt;&lt;a href="#step-3-add-to-blowfish" class="header-anchor"&gt;&lt;/a&gt;Step 3: Add to Blowfish
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0AndWild/0AndWild.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;YOUR_REPO_ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Announcements&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;YOUR_CATEGORY_ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-reactions-enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-emit-metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-input-position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;preferred_color_scheme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-4-configure-paramstoml"&gt;&lt;a href="#step-4-configure-paramstoml" class="header-anchor"&gt;&lt;/a&gt;Step 4: Configure params.toml
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="theme-synchronization-dark-mode"&gt;&lt;a href="#theme-synchronization-dark-mode" class="header-anchor"&gt;&lt;/a&gt;Theme Synchronization (Dark Mode)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Change Giscus theme when blog theme changes
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;giscusTheme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;iframe.giscus-frame&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;giscusTheme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data-theme&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;giscusTheme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;giscus&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;setConfig&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;dark&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://giscus.app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="cost"&gt;&lt;a href="#cost" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Completely free&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="recommended-for"&gt;&lt;a href="#recommended-for" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Developer blogs&lt;/li&gt;
&lt;li&gt;✅ Technical documentation&lt;/li&gt;
&lt;li&gt;✅ Open source project blogs&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="2-utterances"&gt;&lt;a href="#2-utterances" class="header-anchor"&gt;&lt;/a&gt;2. Utterances
&lt;/h2&gt;&lt;h3 id="concept-1"&gt;&lt;a href="#concept-1" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Comment system using GitHub Issues as backend (predecessor of Giscus)&lt;/p&gt;
&lt;h3 id="how-it-works-1"&gt;&lt;a href="#how-it-works-1" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. GitHub OAuth login
 ↓
2. Write comment
 ↓
3. Save to GitHub Issues (each post = 1 Issue)
 ↓
4. Display on blog
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-1"&gt;&lt;a href="#advantages-1" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Completely free&lt;/li&gt;
&lt;li&gt;✅ Lightweight (TypeScript)&lt;/li&gt;
&lt;li&gt;✅ Simple setup&lt;/li&gt;
&lt;li&gt;✅ Markdown support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-1"&gt;&lt;a href="#disadvantages-1" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Uses Issues&lt;/strong&gt; (less suitable than Discussions)&lt;/li&gt;
&lt;li&gt;❌ Fewer features than Giscus&lt;/li&gt;
&lt;li&gt;❌ No anonymous comments&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="giscus-vs-utterances"&gt;&lt;a href="#giscus-vs-utterances" class="header-anchor"&gt;&lt;/a&gt;Giscus vs Utterances
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th&gt;Giscus&lt;/th&gt;
					&lt;th&gt;Utterances&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Backend&lt;/td&gt;
					&lt;td&gt;Discussions&lt;/td&gt;
					&lt;td&gt;Issues&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Reactions&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Nested Replies&lt;/td&gt;
					&lt;td&gt;✅ (nested)&lt;/td&gt;
					&lt;td&gt;⚠️ (flat)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Suitability&lt;/td&gt;
					&lt;td&gt;Comment-specific&lt;/td&gt;
					&lt;td&gt;Issue tracking&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: Giscus is a superior alternative to Utterances&lt;/p&gt;
&lt;h3 id="implementation-difficulty-1"&gt;&lt;a href="#implementation-difficulty-1" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐ (2/5)&lt;/p&gt;
&lt;h3 id="setup-method-1"&gt;&lt;a href="#setup-method-1" class="header-anchor"&gt;&lt;/a&gt;Setup Method
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://utteranc.es/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;username/repository&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;issue-term&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github-light&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="recommended-for-1"&gt;&lt;a href="#recommended-for-1" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Unless there&amp;rsquo;s a specific reason, &lt;strong&gt;use Giscus instead&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="3-remark42-highly-recommended---anonymous--social-login"&gt;&lt;a href="#3-remark42-highly-recommended---anonymous--social-login" class="header-anchor"&gt;&lt;/a&gt;3. Remark42 (Highly Recommended - Anonymous + Social Login)
&lt;/h2&gt;&lt;h3 id="concept-2"&gt;&lt;a href="#concept-2" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Open-source self-hosted comment system supporting anonymous and various social logins&lt;/p&gt;
&lt;h3 id="how-it-works-2"&gt;&lt;a href="#how-it-works-2" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Deploy Remark42 server (Docker)
 ↓
2. Insert Remark42 script on blog
 ↓
3. User chooses:
 - Write anonymous comment
 - Login with GitHub/Google/Twitter and write
 ↓
4. Save to Remark42 DB
 ↓
5. Display on blog
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-2"&gt;&lt;a href="#advantages-2" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Anonymous comments supported&lt;/strong&gt; (can be toggled on/off)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Various social logins&lt;/strong&gt; (GitHub, Google, Facebook, Twitter, Email)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Completely free&lt;/strong&gt; (open source)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No ads&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Data ownership&lt;/strong&gt; (your server)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Markdown support&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Comment edit/delete&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Admin mode&lt;/strong&gt; (approve/block/delete comments)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Notifications&lt;/strong&gt; (Email/Telegram)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Import/Export&lt;/strong&gt; (migrate from other systems)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Voting&lt;/strong&gt; (upvote/downvote)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Spam filter&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-2"&gt;&lt;a href="#disadvantages-2" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Self-hosting required&lt;/strong&gt; (Docker server)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Maintenance responsibility&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Hosting costs&lt;/strong&gt; ($5/month~, free tier possible)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-2"&gt;&lt;a href="#implementation-difficulty-2" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐⭐ (4/5)&lt;/p&gt;
&lt;h3 id="hosting-options"&gt;&lt;a href="#hosting-options" class="header-anchor"&gt;&lt;/a&gt;Hosting Options
&lt;/h3&gt;&lt;h4 id="option-1-railway-recommended"&gt;&lt;a href="#option-1-railway-recommended" class="header-anchor"&gt;&lt;/a&gt;Option 1: Railway (Recommended)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Sign up &lt;span class="k"&gt;for&lt;/span&gt; Railway.app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. &lt;span class="s2"&gt;&amp;#34;New Project&amp;#34;&lt;/span&gt; → &lt;span class="s2"&gt;&amp;#34;Deploy from GitHub&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Select Remark42 Docker image
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Configure environment variables:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;REMARK_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://your-remark42.railway.app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-random-secret
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;AUTH_ANON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Allow anonymous comments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;AUTH_GITHUB_CID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_client_id
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;AUTH_GITHUB_CSEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_client_secret
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Railway Free Tier&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$5 credit per month&lt;/li&gt;
&lt;li&gt;Sufficient for small blogs&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="option-2-flyio"&gt;&lt;a href="#option-2-flyio" class="header-anchor"&gt;&lt;/a&gt;Option 2: Fly.io
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# fly.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;my-remark42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;build&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;umputun/remark42:latest&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;env&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;REMARK_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://my-remark42.fly.dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;AUTH_ANON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;AUTH_GITHUB_CID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;AUTH_GITHUB_CSEC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fly launch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;fly deploy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Fly.io Free Tier&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 apps&lt;/li&gt;
&lt;li&gt;Sufficient for small blogs&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="option-3-docker-compose-vps"&gt;&lt;a href="#option-3-docker-compose-vps" class="header-anchor"&gt;&lt;/a&gt;Option 3: Docker Compose (VPS)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# docker-compose.yml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;remark42&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;umputun/remark42:latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;always&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;REMARK_URL=https://remark.your-blog.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;SECRET=your-secret-key-change-this&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;AUTH_ANON=true &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Allow anonymous&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;AUTH_GITHUB_CID=xxx &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# GitHub login&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;AUTH_GITHUB_CSEC=xxx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;AUTH_GOOGLE_CID=xxx &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Google login&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;AUTH_GOOGLE_CSEC=xxx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ADMIN_SHARED_ID=github_username &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Admin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./data:/srv/var&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8080:8080&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="blog-embed-code"&gt;&lt;a href="#blog-embed-code" class="header-anchor"&gt;&lt;/a&gt;Blog Embed Code
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;remark42&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;remark_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://your-remark42.railway.app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;site_id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0andwild-blog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;embed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;max_shown_comments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;simple_view&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;no_footer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;remark_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/web/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;remark_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;embed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="anonymous--github-simultaneous-configuration"&gt;&lt;a href="#anonymous--github-simultaneous-configuration" class="header-anchor"&gt;&lt;/a&gt;Anonymous + GitHub Simultaneous Configuration
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Environment variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_ANON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Allow anonymous&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_GITHUB_CID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxx &lt;span class="c1"&gt;# GitHub OAuth App ID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_GITHUB_CSEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxx &lt;span class="c1"&gt;# GitHub OAuth App Secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ANON_VOTE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# Disable voting for anonymous (spam prevention)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Users can choose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Comment anonymously&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Login with GitHub&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="admin-features"&gt;&lt;a href="#admin-features" class="header-anchor"&gt;&lt;/a&gt;Admin Features
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Designate admin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ADMIN_SHARED_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;github_yourusername
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Or by email&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ADMIN_SHARED_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;you@example.com
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Admin capabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delete comments&lt;/li&gt;
&lt;li&gt;Block users&lt;/li&gt;
&lt;li&gt;Pin comments&lt;/li&gt;
&lt;li&gt;Read-only mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cost-1"&gt;&lt;a href="#cost-1" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Railway&lt;/strong&gt;: Free or $5/month&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fly.io&lt;/strong&gt;: Free tier available&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;VPS (DigitalOcean, etc.)&lt;/strong&gt;: $5/month~&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="recommended-for-2"&gt;&lt;a href="#recommended-for-2" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Want both anonymous and social login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ Users comfortable with Docker&lt;/li&gt;
&lt;li&gt;✅ Want complete data control&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="4-commento--comentario"&gt;&lt;a href="#4-commento--comentario" class="header-anchor"&gt;&lt;/a&gt;4. Commento / Comentario
&lt;/h2&gt;&lt;h3 id="concept-3"&gt;&lt;a href="#concept-3" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Privacy-focused lightweight comment system&lt;/p&gt;
&lt;h3 id="commento-vs-comentario"&gt;&lt;a href="#commento-vs-comentario" class="header-anchor"&gt;&lt;/a&gt;Commento vs Comentario
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;Commento&lt;/th&gt;
					&lt;th&gt;Comentario&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Status&lt;/td&gt;
					&lt;td&gt;Development stopped&lt;/td&gt;
					&lt;td&gt;Actively developed (Commento fork)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;License&lt;/td&gt;
					&lt;td&gt;MIT&lt;/td&gt;
					&lt;td&gt;MIT&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Language&lt;/td&gt;
					&lt;td&gt;Go&lt;/td&gt;
					&lt;td&gt;Go&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Recommend&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: Comentario recommended&lt;/p&gt;
&lt;h3 id="comentario-advantages"&gt;&lt;a href="#comentario-advantages" class="header-anchor"&gt;&lt;/a&gt;Comentario Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Anonymous comments supported&lt;/li&gt;
&lt;li&gt;✅ Social logins (GitHub, Google, GitLab, SSO)&lt;/li&gt;
&lt;li&gt;✅ Lightweight (Go-based)&lt;/li&gt;
&lt;li&gt;✅ Privacy-focused&lt;/li&gt;
&lt;li&gt;✅ Markdown support&lt;/li&gt;
&lt;li&gt;✅ Voting feature&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-3"&gt;&lt;a href="#disadvantages-3" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ Self-hosting required&lt;/li&gt;
&lt;li&gt;❌ Fewer features than Remark42&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-3"&gt;&lt;a href="#implementation-difficulty-3" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐⭐ (4/5)&lt;/p&gt;
&lt;h3 id="docker-deployment"&gt;&lt;a href="#docker-deployment" class="header-anchor"&gt;&lt;/a&gt;Docker Deployment
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;3.8&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;comentario&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;registry.gitlab.com/comentario/comentario&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;8080:8080&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;COMENTARIO_ORIGIN=https://comments.your-blog.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;COMENTARIO_BIND=0.0.0.0:8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;COMENTARIO_POSTGRES=postgres://user:pass@db/comentario&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;db&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;postgres:15&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;POSTGRES_DB=comentario&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;POSTGRES_USER=comentario&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;POSTGRES_PASSWORD=change-this&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;postgres_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="blog-embed"&gt;&lt;a href="#blog-embed" class="header-anchor"&gt;&lt;/a&gt;Blog Embed
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://comments.your-blog.com/js/commento.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;commento&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="recommended-for-3"&gt;&lt;a href="#recommended-for-3" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Alternative to Remark42&lt;/li&gt;
&lt;li&gt;Want simpler system&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="5-disqus-traditional-saas"&gt;&lt;a href="#5-disqus-traditional-saas" class="header-anchor"&gt;&lt;/a&gt;5. Disqus (Traditional SaaS)
&lt;/h2&gt;&lt;h3 id="concept-4"&gt;&lt;a href="#concept-4" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Oldest and most widely used cloud comment system&lt;/p&gt;
&lt;h3 id="how-it-works-3"&gt;&lt;a href="#how-it-works-3" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Create Disqus account and register site
 ↓
2. Insert Disqus script on blog
 ↓
3. User chooses:
 - Guest (anonymous - requires email)
 - Disqus account
 - Facebook/Twitter/Google login
 ↓
4. Save to Disqus server
 ↓
5. Display on blog
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-3"&gt;&lt;a href="#advantages-3" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Extremely simple setup&lt;/strong&gt; (5 minutes)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No server required&lt;/strong&gt; (SaaS)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Guest mode&lt;/strong&gt; (comment with just email)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Social logins&lt;/strong&gt; (Facebook, Twitter, Google)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Powerful admin tools&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Spam filter&lt;/strong&gt; (Akismet integration)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Mobile apps&lt;/strong&gt; (iOS/Android)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Analytics/Statistics&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-4"&gt;&lt;a href="#disadvantages-4" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Shows ads&lt;/strong&gt; (free plan)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Heavy&lt;/strong&gt; (script size)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Privacy concerns&lt;/strong&gt; (data tracking)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;No data ownership&lt;/strong&gt; (Disqus servers)&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;No GitHub login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Ad removal cost&lt;/strong&gt; ($11.99/month~)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-4"&gt;&lt;a href="#implementation-difficulty-4" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐ (1/5) - Easiest&lt;/p&gt;
&lt;h3 id="setup-method-2"&gt;&lt;a href="#setup-method-2" class="header-anchor"&gt;&lt;/a&gt;Setup Method
&lt;/h3&gt;&lt;h4 id="step-1-register-disqus-site"&gt;&lt;a href="#step-1-register-disqus-site" class="header-anchor"&gt;&lt;/a&gt;Step 1: Register Disqus Site
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Sign up at disqus.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Select &lt;span class="s2"&gt;&amp;#34;I want to install Disqus on my site&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Enter Website Name &lt;span class="o"&gt;(&lt;/span&gt;e.g., andwild-blog&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Select Category
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. Select Plan &lt;span class="o"&gt;(&lt;/span&gt;Basic - Free&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-2-configure-blowfish"&gt;&lt;a href="#step-2-configure-blowfish" class="header-anchor"&gt;&lt;/a&gt;Step 2: Configure Blowfish
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# config/_default/config.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disqus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;shortname&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;andwild-blog&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;# Name created in Step 1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# config/_default/params.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Hugo has built-in Disqus support, so comments display automatically!&lt;/p&gt;
&lt;h4 id="step-3-allow-guest-comments"&gt;&lt;a href="#step-3-allow-guest-comments" class="header-anchor"&gt;&lt;/a&gt;Step 3: Allow Guest Comments
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Disqus Dashboard → Settings → Community
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ Guest Commenting: Allow guests to comment &lt;span class="o"&gt;(&lt;/span&gt;check&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="ad-removal-methods"&gt;&lt;a href="#ad-removal-methods" class="header-anchor"&gt;&lt;/a&gt;Ad Removal Methods
&lt;/h3&gt;&lt;h4 id="method-1-paid-plan-1199month"&gt;&lt;a href="#method-1-paid-plan-1199month" class="header-anchor"&gt;&lt;/a&gt;Method 1: Paid Plan ($11.99/month~)
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;Plus Plan: No ads&lt;/li&gt;
&lt;li&gt;Pro Plan: No ads + advanced features&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="method-2-hide-with-css-not-recommended---may-violate-terms"&gt;&lt;a href="#method-2-hide-with-css-not-recommended---may-violate-terms" class="header-anchor"&gt;&lt;/a&gt;Method 2: Hide with CSS (Not recommended - may violate terms)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;/* Not recommended: May violate Disqus terms */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;disqus_thread&lt;/span&gt; &lt;span class="nt"&gt;iframe&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;*=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ads&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;none&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="cost-2"&gt;&lt;a href="#cost-2" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free&lt;/strong&gt;: With ads&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plus&lt;/strong&gt;: $11.99/month (no ads)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pro&lt;/strong&gt;: $89/month (advanced features)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="recommended-for-4"&gt;&lt;a href="#recommended-for-4" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Want to add comments quickly&lt;/li&gt;
&lt;li&gt;✅ Non-technical bloggers&lt;/li&gt;
&lt;li&gt;✅ Don&amp;rsquo;t mind ads&lt;/li&gt;
&lt;li&gt;❌ Not recommended for privacy-conscious users&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="6-cusdis-free-vercel-deployment"&gt;&lt;a href="#6-cusdis-free-vercel-deployment" class="header-anchor"&gt;&lt;/a&gt;6. Cusdis (Free Vercel Deployment)
&lt;/h2&gt;&lt;h3 id="concept-5"&gt;&lt;a href="#concept-5" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Lightweight open-source comment system, deployable to Vercel for free&lt;/p&gt;
&lt;h3 id="how-it-works-4"&gt;&lt;a href="#how-it-works-4" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Deploy Cusdis to Vercel (1-Click)
 ↓
2. Connect PostgreSQL (Vercel free)
 ↓
3. Add site in dashboard
 ↓
4. Insert script on blog
 ↓
5. Users comment with email + name
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-4"&gt;&lt;a href="#advantages-4" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Completely free&lt;/strong&gt; (Vercel free tier)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Anonymous comments&lt;/strong&gt; (just email + name)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Lightweight&lt;/strong&gt; (50KB)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Simple setup&lt;/strong&gt; (Vercel 1-Click deploy)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Privacy-focused&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Open source&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-5"&gt;&lt;a href="#disadvantages-5" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ No Markdown support&lt;/li&gt;
&lt;li&gt;❌ No social login&lt;/li&gt;
&lt;li&gt;❌ Simple features&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-5"&gt;&lt;a href="#implementation-difficulty-5" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐ (3/5)&lt;/p&gt;
&lt;h3 id="setup-method-3"&gt;&lt;a href="#setup-method-3" class="header-anchor"&gt;&lt;/a&gt;Setup Method
&lt;/h3&gt;&lt;h4 id="step-1-deploy-to-vercel"&gt;&lt;a href="#step-1-deploy-to-vercel" class="header-anchor"&gt;&lt;/a&gt;Step 1: Deploy to Vercel
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Visit https://cusdis.com/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Click &lt;span class="s2"&gt;&amp;#34;Deploy with Vercel&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Connect GitHub
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Add PostgreSQL &lt;span class="o"&gt;(&lt;/span&gt;Vercel Storage&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. Deployment &lt;span class="nb"&gt;complete&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-2-add-site"&gt;&lt;a href="#step-2-add-site" class="header-anchor"&gt;&lt;/a&gt;Step 2: Add Site
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Access deployed Cusdis dashboard
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Click &lt;span class="s2"&gt;&amp;#34;Add Website&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Enter Domain: 0andwild.github.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Copy App ID
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-3-blog-embed"&gt;&lt;a href="#step-3-blog-embed" class="header-anchor"&gt;&lt;/a&gt;Step 3: Blog Embed
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;cusdis_thread&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://your-cusdis.vercel.app&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-app-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;YOUR_APP_ID&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-page-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .File.UniqueID }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-page-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-page-title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;{{ .Title }}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://your-cusdis.vercel.app/js/cusdis.es.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="cost-3"&gt;&lt;a href="#cost-3" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Completely free&lt;/strong&gt; (Vercel free tier)&lt;/p&gt;
&lt;h3 id="recommended-for-5"&gt;&lt;a href="#recommended-for-5" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Need only simple anonymous comments&lt;/li&gt;
&lt;li&gt;✅ Want completely free solution&lt;/li&gt;
&lt;li&gt;✅ Have Vercel experience&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="7-hashover"&gt;&lt;a href="#7-hashover" class="header-anchor"&gt;&lt;/a&gt;7. HashOver
&lt;/h2&gt;&lt;h3 id="concept-6"&gt;&lt;a href="#concept-6" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;PHP-based fully anonymous comment system&lt;/p&gt;
&lt;h3 id="advantages-5"&gt;&lt;a href="#advantages-5" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ Fully anonymous (no information needed)&lt;/li&gt;
&lt;li&gt;✅ PHP + flat file (no DB required)&lt;/li&gt;
&lt;li&gt;✅ Open source&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-6"&gt;&lt;a href="#disadvantages-6" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ Requires PHP (unsuitable for static sites)&lt;/li&gt;
&lt;li&gt;❌ No GitHub login&lt;/li&gt;
&lt;li&gt;❌ Old project&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-6"&gt;&lt;a href="#implementation-difficulty-6" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐⭐ (4/5)&lt;/p&gt;
&lt;h3 id="recommended-for-6"&gt;&lt;a href="#recommended-for-6" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Not recommended for static blogs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Consider only if you have a PHP server&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="8-hyvor-talk-premium-saas"&gt;&lt;a href="#8-hyvor-talk-premium-saas" class="header-anchor"&gt;&lt;/a&gt;8. Hyvor Talk (Premium SaaS)
&lt;/h2&gt;&lt;h3 id="concept-7"&gt;&lt;a href="#concept-7" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Ad-free premium comment system&lt;/p&gt;
&lt;h3 id="advantages-6"&gt;&lt;a href="#advantages-6" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ No ads&lt;/li&gt;
&lt;li&gt;✅ Anonymous comments supported&lt;/li&gt;
&lt;li&gt;✅ Social logins&lt;/li&gt;
&lt;li&gt;✅ Powerful spam filter&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-7"&gt;&lt;a href="#disadvantages-7" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Paid&lt;/strong&gt; ($5/month~)&lt;/li&gt;
&lt;li&gt;❌ No GitHub login&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="cost-4"&gt;&lt;a href="#cost-4" class="header-anchor"&gt;&lt;/a&gt;Cost
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Starter&lt;/strong&gt;: $5/month (1 site)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pro&lt;/strong&gt;: $15/month (3 sites)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="recommended-for-7"&gt;&lt;a href="#recommended-for-7" class="header-anchor"&gt;&lt;/a&gt;Recommended For
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Paid alternative to Disqus&lt;/li&gt;
&lt;li&gt;Want ad-free SaaS&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="comparison-tables"&gt;&lt;a href="#comparison-tables" class="header-anchor"&gt;&lt;/a&gt;Comparison Tables
&lt;/h2&gt;&lt;h3 id="by-authentication-method-1"&gt;&lt;a href="#by-authentication-method-1" class="header-anchor"&gt;&lt;/a&gt;By Authentication Method
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;System&lt;/th&gt;
					&lt;th&gt;Anonymous&lt;/th&gt;
					&lt;th&gt;GitHub&lt;/th&gt;
					&lt;th&gt;Google&lt;/th&gt;
					&lt;th&gt;Other Social&lt;/th&gt;
					&lt;th&gt;Difficulty&lt;/th&gt;
					&lt;th&gt;Cost&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Giscus&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⭐⭐&lt;/td&gt;
					&lt;td&gt;Free&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Utterances&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⭐⭐&lt;/td&gt;
					&lt;td&gt;Free&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Remark42&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;$5/mo&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Comentario&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;$5/mo&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Disqus&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐&lt;/td&gt;
					&lt;td&gt;Free (ads)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cusdis&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;Free&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Hyvor Talk&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐&lt;/td&gt;
					&lt;td&gt;$5/mo&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="by-features"&gt;&lt;a href="#by-features" class="header-anchor"&gt;&lt;/a&gt;By Features
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;System&lt;/th&gt;
					&lt;th&gt;Markdown&lt;/th&gt;
					&lt;th&gt;Reactions&lt;/th&gt;
					&lt;th&gt;Voting&lt;/th&gt;
					&lt;th&gt;Notifications&lt;/th&gt;
					&lt;th&gt;Admin&lt;/th&gt;
					&lt;th&gt;Spam Filter&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Giscus&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Remark42&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Disqus&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cusdis&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="by-hosting"&gt;&lt;a href="#by-hosting" class="header-anchor"&gt;&lt;/a&gt;By Hosting
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;System&lt;/th&gt;
					&lt;th&gt;Hosting&lt;/th&gt;
					&lt;th&gt;Data Location&lt;/th&gt;
					&lt;th&gt;Dependency&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Giscus&lt;/td&gt;
					&lt;td&gt;GitHub&lt;/td&gt;
					&lt;td&gt;GitHub Discussions&lt;/td&gt;
					&lt;td&gt;GitHub&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Remark42&lt;/td&gt;
					&lt;td&gt;Self&lt;/td&gt;
					&lt;td&gt;Your server&lt;/td&gt;
					&lt;td&gt;Docker&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Disqus&lt;/td&gt;
					&lt;td&gt;Disqus&lt;/td&gt;
					&lt;td&gt;Disqus servers&lt;/td&gt;
					&lt;td&gt;Disqus&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cusdis&lt;/td&gt;
					&lt;td&gt;Vercel&lt;/td&gt;
					&lt;td&gt;Vercel DB&lt;/td&gt;
					&lt;td&gt;Vercel&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="selection-guide"&gt;&lt;a href="#selection-guide" class="header-anchor"&gt;&lt;/a&gt;Selection Guide
&lt;/h2&gt;&lt;h3 id="scenario-based-recommendations"&gt;&lt;a href="#scenario-based-recommendations" class="header-anchor"&gt;&lt;/a&gt;Scenario-Based Recommendations
&lt;/h3&gt;&lt;h4 id="1-developer-blog-targeting-github-users"&gt;&lt;a href="#1-developer-blog-targeting-github-users" class="header-anchor"&gt;&lt;/a&gt;1. &amp;ldquo;Developer blog, targeting GitHub users&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Giscus&lt;/strong&gt; ⭐⭐⭐⭐⭐&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Free, simple, Markdown support&lt;/li&gt;
&lt;li&gt;GitHub integration makes notifications convenient&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="2-general-blog-anonymous-comments-essential"&gt;&lt;a href="#2-general-blog-anonymous-comments-essential" class="header-anchor"&gt;&lt;/a&gt;2. &amp;ldquo;General blog, anonymous comments essential&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Cusdis&lt;/strong&gt; (simple) or &lt;strong&gt;Remark42&lt;/strong&gt; (advanced)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cusdis: 5-minute setup, completely free&lt;/li&gt;
&lt;li&gt;Remark42: More features, includes social login&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="3-both-anonymous--github-login"&gt;&lt;a href="#3-both-anonymous--github-login" class="header-anchor"&gt;&lt;/a&gt;3. &amp;ldquo;Both anonymous + GitHub login&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Remark42&lt;/strong&gt; ⭐⭐⭐⭐⭐&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only option supporting both&lt;/li&gt;
&lt;li&gt;Powerful admin features&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="4-no-technical-skills-quick-setup"&gt;&lt;a href="#4-no-technical-skills-quick-setup" class="header-anchor"&gt;&lt;/a&gt;4. &amp;ldquo;No technical skills, quick setup&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Disqus&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;5-minute setup&lt;/li&gt;
&lt;li&gt;Accept ads&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="5-completely-free--dont-want-server-management"&gt;&lt;a href="#5-completely-free--dont-want-server-management" class="header-anchor"&gt;&lt;/a&gt;5. &amp;ldquo;Completely free + don&amp;rsquo;t want server management&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Giscus&lt;/strong&gt; (GitHub) or &lt;strong&gt;Cusdis&lt;/strong&gt; (anonymous)&lt;/p&gt;
&lt;h4 id="6-privacy-is-top-priority"&gt;&lt;a href="#6-privacy-is-top-priority" class="header-anchor"&gt;&lt;/a&gt;6. &amp;ldquo;Privacy is top priority&amp;rdquo;
&lt;/h4&gt;&lt;p&gt;→ &lt;strong&gt;Remark42&lt;/strong&gt; or &lt;strong&gt;Comentario&lt;/strong&gt; (self-hosted)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complete data control&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="practical-implementation-blowfish--giscus"&gt;&lt;a href="#practical-implementation-blowfish--giscus" class="header-anchor"&gt;&lt;/a&gt;Practical Implementation: Blowfish + Giscus
&lt;/h2&gt;&lt;h3 id="complete-setup-process"&gt;&lt;a href="#complete-setup-process" class="header-anchor"&gt;&lt;/a&gt;Complete Setup Process
&lt;/h3&gt;&lt;h4 id="1-enable-github-discussions"&gt;&lt;a href="#1-enable-github-discussions" class="header-anchor"&gt;&lt;/a&gt;1. Enable GitHub Discussions
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GitHub Repository → Settings → Features → Check Discussions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="2-install-giscus-app"&gt;&lt;a href="#2-install-giscus-app" class="header-anchor"&gt;&lt;/a&gt;2. Install Giscus App
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Visit https://github.com/apps/giscus → Install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;→ Select repository
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-generate-giscus-configuration"&gt;&lt;a href="#3-generate-giscus-configuration" class="header-anchor"&gt;&lt;/a&gt;3. Generate Giscus Configuration
&lt;/h4&gt;&lt;p&gt;At &lt;a class="link" href="https://giscus.app" target="_blank" rel="noopener"
 &gt;giscus.app&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Repository: 0AndWild/0AndWild.github.io
Mapping: pathname
Category: Announcements
Theme: preferred_color_scheme
Language: en
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Copy generated code&lt;/p&gt;
&lt;h4 id="4-create-file"&gt;&lt;a href="#4-create-file" class="header-anchor"&gt;&lt;/a&gt;4. Create File
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create directory (if not exists)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p layouts/partials
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;touch layouts/partials/comments.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="5-insert-code"&gt;&lt;a href="#5-insert-code" class="header-anchor"&gt;&lt;/a&gt;5. Insert Code
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://giscus.app/client.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0AndWild/0AndWild.github.io&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-repo-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;R_xxxxxxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Announcements&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-category-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;DIC_xxxxxxxxxxxxx&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;pathname&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-reactions-enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-emit-metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-input-position&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;preferred_color_scheme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;data-lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;anonymous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;async&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="6-modify-paramstoml"&gt;&lt;a href="#6-modify-paramstoml" class="header-anchor"&gt;&lt;/a&gt;6. Modify params.toml
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="7-local-testing"&gt;&lt;a href="#7-local-testing" class="header-anchor"&gt;&lt;/a&gt;7. Local Testing
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Check at http://localhost:1313&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="8-deploy"&gt;&lt;a href="#8-deploy" class="header-anchor"&gt;&lt;/a&gt;8. Deploy
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;Add Giscus comments&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="practical-implementation-blowfish--remark42-railway"&gt;&lt;a href="#practical-implementation-blowfish--remark42-railway" class="header-anchor"&gt;&lt;/a&gt;Practical Implementation: Blowfish + Remark42 (Railway)
&lt;/h2&gt;&lt;h3 id="complete-setup-process-1"&gt;&lt;a href="#complete-setup-process-1" class="header-anchor"&gt;&lt;/a&gt;Complete Setup Process
&lt;/h3&gt;&lt;h4 id="1-create-github-oauth-app"&gt;&lt;a href="#1-create-github-oauth-app" class="header-anchor"&gt;&lt;/a&gt;1. Create GitHub OAuth App
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GitHub → Settings → Developer settings → OAuth Apps → New OAuth App
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Application name: AndWild Blog Comments
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Homepage URL: https://0andwild.github.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Authorization callback URL: https://your-remark42.railway.app/auth/github/callback
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;After creation:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Copy Client ID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generate and copy Client Secret
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="2-deploy-to-railway"&gt;&lt;a href="#2-deploy-to-railway" class="header-anchor"&gt;&lt;/a&gt;2. Deploy to Railway
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Sign up &lt;span class="k"&gt;for&lt;/span&gt; railway.app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. &lt;span class="s2"&gt;&amp;#34;New Project&amp;#34;&lt;/span&gt; → &lt;span class="s2"&gt;&amp;#34;Deploy Docker Image&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Image: umputun/remark42:latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Add environment variables:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;REMARK_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://your-project.railway.app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;randomly-generated-secret-key-change-this
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;SITE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0andwild-blog
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_ANON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_GITHUB_CID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_github_client_id
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;AUTH_GITHUB_CSEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_github_client_secret
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;ADMIN_SHARED_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;github_yourusername
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-verify-deployment"&gt;&lt;a href="#3-verify-deployment" class="header-anchor"&gt;&lt;/a&gt;3. Verify Deployment
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Railway automatically generates URL:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://your-project.railway.app
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Access in browser to verify Remark42 UI
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="4-configure-blowfish"&gt;&lt;a href="#4-configure-blowfish" class="header-anchor"&gt;&lt;/a&gt;4. Configure Blowfish
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p layouts/partials
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;touch layouts/partials/comments.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/partials/comments.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;remark42&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;remark_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://your-project.railway.app&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;site_id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0andwild-blog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;embed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;light&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;script&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;remark_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/web/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.js&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;remark_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;embed&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="5-paramstoml"&gt;&lt;a href="#5-paramstoml" class="header-anchor"&gt;&lt;/a&gt;5. params.toml
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-toml" data-lang="toml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;showComments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="6-test-and-deploy"&gt;&lt;a href="#6-test-and-deploy" class="header-anchor"&gt;&lt;/a&gt;6. Test and Deploy
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# After verification&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -m &lt;span class="s2"&gt;&amp;#34;Add Remark42 comments&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git push
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="migration-guide"&gt;&lt;a href="#migration-guide" class="header-anchor"&gt;&lt;/a&gt;Migration Guide
&lt;/h2&gt;&lt;h3 id="disqus--giscus"&gt;&lt;a href="#disqus--giscus" class="header-anchor"&gt;&lt;/a&gt;Disqus → Giscus
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Export data from Disqus &lt;span class="o"&gt;(&lt;/span&gt;XML&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Manual migration to GitHub Discussions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;(&lt;/span&gt;No automation script, manual work required&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="disqus--remark42"&gt;&lt;a href="#disqus--remark42" class="header-anchor"&gt;&lt;/a&gt;Disqus → Remark42
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Disqus XML Export
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Remark42 Admin → Import → Select Disqus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Upload XML file
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;h3 id="final-recommendations"&gt;&lt;a href="#final-recommendations" class="header-anchor"&gt;&lt;/a&gt;Final Recommendations
&lt;/h3&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Situation&lt;/th&gt;
					&lt;th&gt;Recommended System&lt;/th&gt;
					&lt;th&gt;Reason&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Developer blog&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Giscus&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Free, GitHub integration, Markdown&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;General blog (anonymous needed)&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Cusdis&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Free, simple, anonymous&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Both anonymous + social&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Remark42&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Flexible, all features&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Quick setup&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Disqus&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;5-minute completion (accept ads)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Complete control&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Remark42&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Self-hosted, customizable&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="personal-recommendation-0andwild-blog"&gt;&lt;a href="#personal-recommendation-0andwild-blog" class="header-anchor"&gt;&lt;/a&gt;Personal Recommendation (0AndWild Blog)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Giscus&lt;/strong&gt; recommended&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Perfect fit for GitHub Pages blog&lt;/li&gt;
&lt;li&gt;Tech blog&amp;rsquo;s main audience is GitHub users&lt;/li&gt;
&lt;li&gt;Free, simple, no maintenance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Alternative&lt;/strong&gt;: Remark42 (when anonymous comments desired)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="quick-start"&gt;&lt;a href="#quick-start" class="header-anchor"&gt;&lt;/a&gt;Quick Start
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start with Giscus&lt;/strong&gt; (10 minutes)&lt;/li&gt;
&lt;li&gt;Collect user feedback&lt;/li&gt;
&lt;li&gt;Consider &lt;strong&gt;switching to Remark42&lt;/strong&gt; if many requests for anonymous comments&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Comment systems can be changed later, so strongly recommend starting with Giscus!&lt;/p&gt;</description></item><item><title>Complete Guide to Blog Subscription and Email Notification Systems</title><link>https://0andwild.com/en/posts/251017_subscription_alert/</link><pubDate>Fri, 17 Oct 2025 10:00:00 +0900</pubDate><guid>https://0andwild.com/en/posts/251017_subscription_alert/</guid><description>&lt;img src="https://0andwild.com/" alt="Featured image of post Complete Guide to Blog Subscription and Email Notification Systems" /&gt;&lt;h2 id="overview"&gt;&lt;a href="#overview" class="header-anchor"&gt;&lt;/a&gt;Overview
&lt;/h2&gt;&lt;p&gt;This guide analyzes methods to add subscription and email notification features to blogs built with static site generators (Hugo). We&amp;rsquo;ll cover everything from basic subscriptions to &lt;strong&gt;keyword-based selective notifications&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-rss-feed--email-services"&gt;&lt;a href="#1-rss-feed--email-services" class="header-anchor"&gt;&lt;/a&gt;1. RSS Feed + Email Services
&lt;/h2&gt;&lt;h3 id="concept"&gt;&lt;a href="#concept" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Leverage services that convert Hugo&amp;rsquo;s built-in RSS Feed into email notifications.&lt;/p&gt;
&lt;h3 id="method-a-blogtrottr"&gt;&lt;a href="#method-a-blogtrottr" class="header-anchor"&gt;&lt;/a&gt;Method A: Blogtrottr
&lt;/h3&gt;&lt;h4 id="how-it-works"&gt;&lt;a href="#how-it-works" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Hugo automatically generates RSS Feed (index.xml)
 ↓
2. Users register RSS URL on Blogtrottr
 ↓
3. Blogtrottr periodically checks RSS
 ↓
4. Sends email when new posts detected
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="advantages"&gt;&lt;a href="#advantages" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;✅ No developer work (just provide link)&lt;/li&gt;
&lt;li&gt;✅ Completely free&lt;/li&gt;
&lt;li&gt;✅ Works immediately&lt;/li&gt;
&lt;li&gt;✅ No server required&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="disadvantages"&gt;&lt;a href="#disadvantages" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;❌ No subscriber management&lt;/li&gt;
&lt;li&gt;❌ No email design customization&lt;/li&gt;
&lt;li&gt;❌ No analytics&lt;/li&gt;
&lt;li&gt;❌ No keyword filtering&lt;/li&gt;
&lt;li&gt;❌ Users must register on external site&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="implementation-difficulty"&gt;&lt;a href="#implementation-difficulty" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h4&gt;&lt;p&gt;⭐ (1/5) - Easiest&lt;/p&gt;
&lt;h4 id="usage-example"&gt;&lt;a href="#usage-example" class="header-anchor"&gt;&lt;/a&gt;Usage Example
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Add link to blog:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[&lt;span class="nt"&gt;Subscribe via Email&lt;/span&gt;](&lt;span class="na"&gt;https://blogtrottr.com&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(Enter https://0andwild.github.io/index.xml on the site)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id="method-b-feedburner-google"&gt;&lt;a href="#method-b-feedburner-google" class="header-anchor"&gt;&lt;/a&gt;Method B: FeedBurner (Google)
&lt;/h3&gt;&lt;h4 id="how-it-works-1"&gt;&lt;a href="#how-it-works-1" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h4&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Register RSS Feed with FeedBurner
 ↓
2. FeedBurner proxies/manages RSS
 ↓
3. Embed subscription form on blog
 ↓
4. Users subscribe directly from blog
 ↓
5. Auto-sends email when new posts published
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="advantages-1"&gt;&lt;a href="#advantages-1" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;✅ Basic analytics provided&lt;/li&gt;
&lt;li&gt;✅ Subscription form provided&lt;/li&gt;
&lt;li&gt;✅ Free&lt;/li&gt;
&lt;li&gt;✅ RSS management features&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="disadvantages-1"&gt;&lt;a href="#disadvantages-1" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;❌ Google may discontinue support (updates stopped)&lt;/li&gt;
&lt;li&gt;❌ No keyword filtering&lt;/li&gt;
&lt;li&gt;❌ Limited customization&lt;/li&gt;
&lt;li&gt;❌ Outdated UI&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="implementation-difficulty-1"&gt;&lt;a href="#implementation-difficulty-1" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h4&gt;&lt;p&gt;⭐⭐ (2/5)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2-mailchimp--rss-campaign-recommended"&gt;&lt;a href="#2-mailchimp--rss-campaign-recommended" class="header-anchor"&gt;&lt;/a&gt;2. Mailchimp + RSS Campaign (Recommended)
&lt;/h2&gt;&lt;h3 id="concept-1"&gt;&lt;a href="#concept-1" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Leverage professional email marketing platform to automatically convert RSS Feed to emails&lt;/p&gt;
&lt;h3 id="how-it-works-2"&gt;&lt;a href="#how-it-works-2" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Create RSS Campaign in Mailchimp
 ↓
2. Register RSS URL and set check frequency (daily/weekly/monthly)
 ↓
3. Embed Mailchimp subscription form on blog
 ↓
4. Users enter email to subscribe
 ↓
5. Auto-generates email template when new post detected
 ↓
6. Sends to all subscribers
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-2"&gt;&lt;a href="#advantages-2" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Free tier&lt;/strong&gt;: Up to 2,000 subscribers&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Professional email design&lt;/strong&gt; (drag-and-drop editor)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Subscriber management&lt;/strong&gt; (add/delete/segment)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Detailed analytics&lt;/strong&gt; (open rate, click rate, unsubscribe rate)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Auto-generated subscription forms&lt;/strong&gt; (embed code provided)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Automation&lt;/strong&gt; (only sends on new posts)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Mobile optimized&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Spam filter avoidance&lt;/strong&gt; (professional sending servers)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-2"&gt;&lt;a href="#disadvantages-2" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ No keyword filtering by default (tag-based segmentation on Pro plan)&lt;/li&gt;
&lt;li&gt;❌ Mailchimp logo shown on free tier&lt;/li&gt;
&lt;li&gt;❌ Paid after 2,000 subscribers ($13/month+)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-2"&gt;&lt;a href="#implementation-difficulty-2" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐ (2/5)&lt;/p&gt;
&lt;h3 id="setup-steps"&gt;&lt;a href="#setup-steps" class="header-anchor"&gt;&lt;/a&gt;Setup Steps
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. Create Mailchimp account
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. Create Audience
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. Campaign → Create → Email → RSS Campaign
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. Enter RSS URL: https://your-blog.com/index.xml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. Set sending frequency &lt;span class="o"&gt;(&lt;/span&gt;Daily/Weekly&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6. Design email template
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7. Copy subscription form code
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8. Insert in Hugo &lt;span class="o"&gt;(&lt;/span&gt;layouts/partials/subscribe.html&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="blog-embed-code-example"&gt;&lt;a href="#blog-embed-code-example" class="header-anchor"&gt;&lt;/a&gt;Blog Embed Code Example
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Mailchimp subscription form --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mc_embed_signup&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://your-mailchimp-url.com/subscribe&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;post&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;EMAIL&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Email address&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Subscribe&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="3-buttondown-developer-friendly-recommended"&gt;&lt;a href="#3-buttondown-developer-friendly-recommended" class="header-anchor"&gt;&lt;/a&gt;3. Buttondown (Developer-Friendly, Recommended)
&lt;/h2&gt;&lt;h3 id="concept-2"&gt;&lt;a href="#concept-2" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Markdown-based newsletter platform with API for customization&lt;/p&gt;
&lt;h3 id="how-it-works-3"&gt;&lt;a href="#how-it-works-3" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Connect RSS Feed to Buttondown
 ↓
2. Auto-converts RSS items to Markdown emails
 ↓
3. Subscribers can select tags/keywords
 ↓
4. Filter subscribers by specific tags via API
 ↓
5. Send only to matching subscribers
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-3"&gt;&lt;a href="#advantages-3" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Free tier&lt;/strong&gt;: Up to 1,000 subscribers&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Markdown-based&lt;/strong&gt; (developer-friendly)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Powerful API&lt;/strong&gt; (customizable)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Tag-based subscriptions&lt;/strong&gt; (keyword filtering possible)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;No ads&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Clean UI&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;RSS import automation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Privacy-focused&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-3"&gt;&lt;a href="#disadvantages-3" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ Simple email design (Markdown only)&lt;/li&gt;
&lt;li&gt;❌ Analytics weaker than Mailchimp&lt;/li&gt;
&lt;li&gt;❌ Limited Korean support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-3"&gt;&lt;a href="#implementation-difficulty-3" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐ (3/5) - Increases with API usage&lt;/p&gt;
&lt;h3 id="keyword-notification-example"&gt;&lt;a href="#keyword-notification-example" class="header-anchor"&gt;&lt;/a&gt;Keyword Notification Example
&lt;/h3&gt;&lt;h4 id="step-1-add-tag-selection-to-subscription-form"&gt;&lt;a href="#step-1-add-tag-selection-to-subscription-form" class="header-anchor"&gt;&lt;/a&gt;Step 1: Add tag selection to subscription form
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://buttondown.email/api/emails/embed-subscribe/YOUR_ID&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;post&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Select topics of interest:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Kubernetes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;docker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Docker
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;golang&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Go
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Subscribe&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-2-selective-sending-via-github-actions"&gt;&lt;a href="#step-2-selective-sending-via-github-actions" class="header-anchor"&gt;&lt;/a&gt;Step 2: Selective sending via GitHub Actions
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Send Newsletter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;content/posts/**&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;send&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Extract tags from post&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; TAGS=$(grep &amp;#34;^tags = &amp;#34; content/posts/*/index.md | cut -d&amp;#39;&amp;#34;&amp;#39; -f2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;POST_TAGS=$TAGS&amp;#34; &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Send to matching subscribers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; curl -X POST https://api.buttondown.email/v1/emails \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -H &amp;#34;Authorization: Token ${{ secrets.BUTTONDOWN_API_KEY }}&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -d &amp;#34;subject=New Post&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -d &amp;#34;body=...&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -d &amp;#34;tag=$POST_TAGS&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="4-sendgrid--github-actions-fully-custom"&gt;&lt;a href="#4-sendgrid--github-actions-fully-custom" class="header-anchor"&gt;&lt;/a&gt;4. SendGrid + GitHub Actions (Fully Custom)
&lt;/h2&gt;&lt;h3 id="concept-3"&gt;&lt;a href="#concept-3" class="header-anchor"&gt;&lt;/a&gt;Concept
&lt;/h3&gt;&lt;p&gt;Build fully customized notification system combining email sending API with CI/CD&lt;/p&gt;
&lt;h3 id="how-it-works-4"&gt;&lt;a href="#how-it-works-4" class="header-anchor"&gt;&lt;/a&gt;How It Works
&lt;/h3&gt;&lt;pre tabindex="0"&gt;&lt;code&gt;1. Write new post and Git Push
 ↓
2. GitHub Actions triggered
 ↓
3. Action parses Front Matter
 - Extract title, summary, tags
 ↓
4. Query subscriber DB (Supabase/JSON file)
 - Match each subscriber&amp;#39;s keywords
 ↓
5. Filter matching subscribers only
 ↓
6. Send individual emails via SendGrid API
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="advantages-4"&gt;&lt;a href="#advantages-4" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Complete control&lt;/strong&gt; (customize all logic)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Perfect keyword notification implementation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Free tier&lt;/strong&gt;: SendGrid 100 emails/month&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Automation&lt;/strong&gt; (just git push)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Scalable&lt;/strong&gt; (DB, logic freely customizable)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Own subscriber data&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="disadvantages-4"&gt;&lt;a href="#disadvantages-4" class="header-anchor"&gt;&lt;/a&gt;Disadvantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;❌ Development work required&lt;/li&gt;
&lt;li&gt;❌ Maintenance burden&lt;/li&gt;
&lt;li&gt;❌ SendGrid free tier limited (100 emails/month)&lt;/li&gt;
&lt;li&gt;❌ Must implement subscription form and DB yourself&lt;/li&gt;
&lt;li&gt;❌ Spam filter avoidance setup needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="implementation-difficulty-4"&gt;&lt;a href="#implementation-difficulty-4" class="header-anchor"&gt;&lt;/a&gt;Implementation Difficulty
&lt;/h3&gt;&lt;p&gt;⭐⭐⭐⭐⭐ (5/5) - Most complex&lt;/p&gt;
&lt;h3 id="architecture"&gt;&lt;a href="#architecture" class="header-anchor"&gt;&lt;/a&gt;Architecture
&lt;/h3&gt;&lt;h4 id="subscriber-database-options"&gt;&lt;a href="#subscriber-database-options" class="header-anchor"&gt;&lt;/a&gt;Subscriber Database Options
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Option A: JSON File (Simple)&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// subscribers.json (encrypted in GitHub repository)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;user@example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;docker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;email&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dev@example.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;golang&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;rust&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;active&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Option B: Supabase (Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- subscribers table
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subscribers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;UNIQUE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- array type
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;BOOLEAN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DEFAULT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="github-actions-workflow"&gt;&lt;a href="#github-actions-workflow" class="header-anchor"&gt;&lt;/a&gt;GitHub Actions Workflow
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Email Notification&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;main]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;content/posts/**&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Setup Node.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/setup-node@v3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;node-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;18&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Extract Post Metadata&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;metadata&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Find most recently modified post
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; POST_FILE=$(git diff-tree --no-commit-id --name-only -r ${{ github.sha }} | grep &amp;#39;content/posts&amp;#39; | head -1)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Parse Front Matter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; TITLE=$(grep &amp;#34;^title = &amp;#34; $POST_FILE | cut -d&amp;#39;&amp;#34;&amp;#39; -f2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; TAGS=$(grep &amp;#34;^tags = &amp;#34; $POST_FILE | sed &amp;#39;s/tags = \[//;s/\]//;s/&amp;#34;//g&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; SUMMARY=$(grep &amp;#34;^summary = &amp;#34; $POST_FILE | cut -d&amp;#39;&amp;#34;&amp;#39; -f2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; URL=&amp;#34;https://0andwild.github.io/$(dirname $POST_FILE | sed &amp;#39;s/content\///&amp;#39;)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;title=$TITLE&amp;#34; &amp;gt;&amp;gt; $GITHUB_OUTPUT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;tags=$TAGS&amp;#34; &amp;gt;&amp;gt; $GITHUB_OUTPUT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;summary=$SUMMARY&amp;#34; &amp;gt;&amp;gt; $GITHUB_OUTPUT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; echo &amp;#34;url=$URL&amp;#34; &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Query Matching Subscribers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;subscribers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Query matching subscribers from Supabase
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; curl -X POST https://YOUR_PROJECT.supabase.co/rest/v1/rpc/get_matching_subscribers \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -H &amp;#34;apikey: ${{ secrets.SUPABASE_KEY }}&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -H &amp;#34;Content-Type: application/json&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -d &amp;#34;{\&amp;#34;post_tags\&amp;#34;: \&amp;#34;${{ steps.metadata.outputs.tags }}\&amp;#34;}&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;gt; subscribers.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Send Emails via SendGrid&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; # Execute Node.js script
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; cat &amp;gt; send-emails.js &amp;lt;&amp;lt; &amp;#39;EOF&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const sgMail = require(&amp;#39;@sendgrid/mail&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const fs = require(&amp;#39;fs&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; sgMail.setApiKey(process.env.SENDGRID_API_KEY);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const subscribers = JSON.parse(fs.readFileSync(&amp;#39;subscribers.json&amp;#39;));
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const title = process.env.POST_TITLE;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const summary = process.env.POST_SUMMARY;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const url = process.env.POST_URL;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; subscribers.forEach(async (subscriber) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; const msg = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; to: subscriber.email,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; from: &amp;#39;noreply@0andwild.github.io&amp;#39;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; subject: `New Post: ${title}`,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; html: `
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;h2&amp;gt;${title}&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;p&amp;gt;${summary}&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;p&amp;gt;Matched keywords: ${subscriber.matched_keywords.join(&amp;#39;, &amp;#39;)}&amp;lt;/p&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;a href=&amp;#34;${url}&amp;#34;&amp;gt;Read Post&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;hr&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;lt;small&amp;gt;&amp;lt;a href=&amp;#34;https://0andwild.github.io/unsubscribe?token=${subscriber.token}&amp;#34;&amp;gt;Unsubscribe&amp;lt;/a&amp;gt;&amp;lt;/small&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; `
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; await sgMail.send(msg);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; console.log(`Email sent to ${subscriber.email}`);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; npm install @sendgrid/mail
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; node send-emails.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;SENDGRID_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.SENDGRID_API_KEY }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POST_TITLE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ steps.metadata.outputs.title }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POST_SUMMARY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ steps.metadata.outputs.summary }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POST_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ steps.metadata.outputs.url }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="subscription-form-implementation-hugo-shortcode"&gt;&lt;a href="#subscription-form-implementation-hugo-shortcode" class="header-anchor"&gt;&lt;/a&gt;Subscription Form Implementation (Hugo Shortcode)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- layouts/shortcodes/subscribe.html --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subscription-form&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Subscribe to Blog&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subscribe-form&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;email&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Email address&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;fieldset&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Select topics of interest (get notified only for selected topics)&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;kubernetes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Kubernetes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;docker&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Docker&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;golang&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Go&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;rust&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; Rust&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;checkbox&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;devops&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; DevOps&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;fieldset&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;submit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Subscribe&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;subscribe-form&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;email&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;input[name=&amp;#34;keywords&amp;#34;]:checked&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Save to Supabase
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://YOUR_PROJECT.supabase.co/rest/v1/subscribers&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;apikey&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;YOUR_ANON_KEY&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Successfully subscribed!&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;An error occurred.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="supabase-function-keyword-matching"&gt;&lt;a href="#supabase-function-keyword-matching" class="header-anchor"&gt;&lt;/a&gt;Supabase Function (Keyword Matching)
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;-- Function to find matching subscribers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;OR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;REPLACE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FUNCTION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;get_matching_subscribers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_tags&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RETURNS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matched_keywords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;RETURN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;QUERY&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ARRAY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unnest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTERSECT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;unnest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string_to_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matched_keywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unsubscribe_token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subscribers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string_to_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- array overlap operator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LANGUAGE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;plpgsql&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="cost-analysis"&gt;&lt;a href="#cost-analysis" class="header-anchor"&gt;&lt;/a&gt;Cost Analysis
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SendGrid&lt;/strong&gt;: 100 emails/month free (then $19.95/month)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supabase&lt;/strong&gt;: 500MB DB, 2GB transfer free per month&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt;: 2,000 minutes/month free&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total cost&lt;/strong&gt;: Completely free (for small blogs)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="5-fully-custom-supabase--github-actions--resend"&gt;&lt;a href="#5-fully-custom-supabase--github-actions--resend" class="header-anchor"&gt;&lt;/a&gt;5. Fully Custom (Supabase + GitHub Actions + Resend)
&lt;/h2&gt;&lt;h3 id="sendgrid-alternative-resend"&gt;&lt;a href="#sendgrid-alternative-resend" class="header-anchor"&gt;&lt;/a&gt;SendGrid Alternative: Resend
&lt;/h3&gt;&lt;p&gt;More developer-friendly modern email API than SendGrid&lt;/p&gt;
&lt;h3 id="advantages-5"&gt;&lt;a href="#advantages-5" class="header-anchor"&gt;&lt;/a&gt;Advantages
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Free tier&lt;/strong&gt;: 3,000 emails/month (30x more than SendGrid!)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Simpler API&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;React Email support&lt;/strong&gt; (write emails in JSX)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Better developer experience&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="resend-usage-example"&gt;&lt;a href="#resend-usage-example" class="header-anchor"&gt;&lt;/a&gt;Resend Usage Example
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Resend&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;resend&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Resend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RESEND_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resend&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;from&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;blog@0andwild.github.io&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`New Post: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sb"&gt;`&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;lt;/p&amp;gt;&amp;lt;a href=&amp;#34;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;&amp;#34;&amp;gt;Read&amp;lt;/a&amp;gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="comparison-table"&gt;&lt;a href="#comparison-table" class="header-anchor"&gt;&lt;/a&gt;Comparison Table
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Method&lt;/th&gt;
					&lt;th&gt;Free Limit&lt;/th&gt;
					&lt;th&gt;Keyword Alerts&lt;/th&gt;
					&lt;th&gt;Difficulty&lt;/th&gt;
					&lt;th&gt;Subscriber Mgmt&lt;/th&gt;
					&lt;th&gt;Custom&lt;/th&gt;
					&lt;th&gt;Recommend&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Blogtrottr&lt;/td&gt;
					&lt;td&gt;Unlimited&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⭐&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;Testing only&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;FeedBurner&lt;/td&gt;
					&lt;td&gt;Unlimited&lt;/td&gt;
					&lt;td&gt;❌&lt;/td&gt;
					&lt;td&gt;⭐⭐&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;Not recommended (discontinued)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Mailchimp&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;2,000&lt;/td&gt;
					&lt;td&gt;⚠️ (Pro)&lt;/td&gt;
					&lt;td&gt;⭐⭐&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⚠️&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;General subscriptions&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Buttondown&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;1,000&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;For developers&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SendGrid + Actions&lt;/td&gt;
					&lt;td&gt;100/month&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅✅&lt;/td&gt;
					&lt;td&gt;Advanced users&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Resend + Actions&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;3,000/month&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
					&lt;td&gt;✅&lt;/td&gt;
					&lt;td&gt;✅✅&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Perfect control&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="recommended-roadmap"&gt;&lt;a href="#recommended-roadmap" class="header-anchor"&gt;&lt;/a&gt;Recommended Roadmap
&lt;/h2&gt;&lt;h3 id="stage-1-quick-start-immediate"&gt;&lt;a href="#stage-1-quick-start-immediate" class="header-anchor"&gt;&lt;/a&gt;Stage 1: Quick Start (Immediate)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Mailchimp RSS Campaign&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;10-minute setup&lt;/li&gt;
&lt;li&gt;All subscribers get all posts&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="stage-2-improvement-after-1-week"&gt;&lt;a href="#stage-2-improvement-after-1-week" class="header-anchor"&gt;&lt;/a&gt;Stage 2: Improvement (After 1 week)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Migrate to Buttondown&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cleaner experience&lt;/li&gt;
&lt;li&gt;Basic tag features&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="stage-3-advanced-features-when-needed"&gt;&lt;a href="#stage-3-advanced-features-when-needed" class="header-anchor"&gt;&lt;/a&gt;Stage 3: Advanced Features (When needed)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Resend + GitHub Actions + Supabase&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keyword-based selective notifications&lt;/li&gt;
&lt;li&gt;Complete control&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;h3 id="for-general-bloggers"&gt;&lt;a href="#for-general-bloggers" class="header-anchor"&gt;&lt;/a&gt;For general bloggers:
&lt;/h3&gt;&lt;p&gt;→ &lt;strong&gt;Mailchimp&lt;/strong&gt; (easiest and most professional)&lt;/p&gt;
&lt;h3 id="for-developer-blogs"&gt;&lt;a href="#for-developer-blogs" class="header-anchor"&gt;&lt;/a&gt;For developer blogs:
&lt;/h3&gt;&lt;p&gt;→ &lt;strong&gt;Buttondown&lt;/strong&gt; (developer-friendly, provides API)&lt;/p&gt;
&lt;h3 id="if-keyword-alerts-are-essential"&gt;&lt;a href="#if-keyword-alerts-are-essential" class="header-anchor"&gt;&lt;/a&gt;If keyword alerts are essential:
&lt;/h3&gt;&lt;p&gt;→ &lt;strong&gt;Resend + GitHub Actions + Supabase&lt;/strong&gt; (fully custom)&lt;/p&gt;
&lt;h3 id="to-test-without-spending-money"&gt;&lt;a href="#to-test-without-spending-money" class="header-anchor"&gt;&lt;/a&gt;To test without spending money:
&lt;/h3&gt;&lt;p&gt;→ &lt;strong&gt;Blogtrottr&lt;/strong&gt; (30-second setup)&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="quick-start"&gt;&lt;a href="#quick-start" class="header-anchor"&gt;&lt;/a&gt;Quick Start
&lt;/h2&gt;&lt;p&gt;If you want actual implementation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with Mailchimp (low learning curve)&lt;/li&gt;
&lt;li&gt;Consider Buttondown when traffic grows&lt;/li&gt;
&lt;li&gt;Build custom solution when advanced features needed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Keyword alerts may be overkill initially, so it&amp;rsquo;s recommended to start with basic subscriptions.&lt;/p&gt;</description></item><item><title>Hugo Markdown Guide</title><link>https://0andwild.com/en/posts/251016_blowfish_markdown/</link><pubDate>Thu, 16 Oct 2025 18:36:52 +0900</pubDate><guid>https://0andwild.com/en/posts/251016_blowfish_markdown/</guid><description>&lt;img src="https://0andwild.com/" alt="Featured image of post Hugo Markdown Guide" /&gt;&lt;!-- Content Writing Guide --&gt;
&lt;h2 id="heading-h2"&gt;&lt;a href="#heading-h2" class="header-anchor"&gt;&lt;/a&gt;Heading (H2)
&lt;/h2&gt;&lt;h3 id="subheading-h3"&gt;&lt;a href="#subheading-h3" class="header-anchor"&gt;&lt;/a&gt;Subheading (H3)
&lt;/h3&gt;&lt;p&gt;Regular text. &lt;strong&gt;Bold&lt;/strong&gt;, &lt;em&gt;Italic&lt;/em&gt;, &lt;del&gt;Strikethrough&lt;/del&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="images"&gt;&lt;a href="#images" class="header-anchor"&gt;&lt;/a&gt;Images
&lt;/h2&gt;&lt;h3 id="method-1-local-image"&gt;&lt;a href="#method-1-local-image" class="header-anchor"&gt;&lt;/a&gt;Method 1: Local Image
&lt;/h3&gt;&lt;p&gt;Place image file in the post folder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;![&lt;span class="nt"&gt;Image description&lt;/span&gt;](&lt;span class="na"&gt;image.jpg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="method-2-external-image-url"&gt;&lt;a href="#method-2-external-image-url" class="header-anchor"&gt;&lt;/a&gt;Method 2: External Image URL
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-markdown" data-lang="markdown"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;![&lt;span class="nt"&gt;Image description&lt;/span&gt;](&lt;span class="na"&gt;https://example.com/image.jpg&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="method-3-html-tag-with-size-control"&gt;&lt;a href="#method-3-html-tag-with-size-control" class="header-anchor"&gt;&lt;/a&gt;Method 3: HTML Tag (with size control)
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;image.jpg&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Image description&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;500&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="carousel-images-slideshow"&gt;&lt;a href="#carousel-images-slideshow" class="header-anchor"&gt;&lt;/a&gt;Carousel Images (Slideshow)
&lt;/h3&gt;&lt;h3 id="169"&gt;&lt;a href="#169" class="header-anchor"&gt;&lt;/a&gt;16:9
&lt;/h3&gt;&lt;div class="stack-carousel" style="--stack-carousel-ratio: ZgotmplZ;"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test1.jpeg" alt="img/test1.jpeg" loading="lazy"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test2.jpeg" alt="img/test2.jpeg" loading="lazy"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test3.jpeg" alt="img/test3.jpeg" loading="lazy"&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h2 id="hahahugoshortcode68s1hbhb"&gt;&lt;a href="#hahahugoshortcode68s1hbhb" class="header-anchor"&gt;&lt;/a&gt;21:9
&lt;div class="stack-carousel" style="--stack-carousel-ratio: ZgotmplZ;"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test1.jpeg" alt="img/test1.jpeg" loading="lazy"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test2.jpeg" alt="img/test2.jpeg" loading="lazy"&gt;&lt;img src="https://0andwild.com/posts/251016_blowfish_markdown/img/test3.jpeg" alt="img/test3.jpeg" loading="lazy"&gt;&lt;/div&gt;

&lt;/h2&gt;&lt;h2 id="code-blocks"&gt;&lt;a href="#code-blocks" class="header-anchor"&gt;&lt;/a&gt;Code Blocks
&lt;/h2&gt;&lt;h3 id="inline-code"&gt;&lt;a href="#inline-code" class="header-anchor"&gt;&lt;/a&gt;Inline Code
&lt;/h3&gt;&lt;p&gt;Use &lt;code&gt;inline code&lt;/code&gt; format&lt;/p&gt;
&lt;h3 id="code-blocks-1"&gt;&lt;a href="#code-blocks-1" class="header-anchor"&gt;&lt;/a&gt;Code Blocks
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d -p 8080:80 nginx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="links"&gt;&lt;a href="#links" class="header-anchor"&gt;&lt;/a&gt;Links
&lt;/h2&gt;&lt;h3 id="basic-link"&gt;&lt;a href="#basic-link" class="header-anchor"&gt;&lt;/a&gt;Basic Link
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://example.com" target="_blank" rel="noopener"
 &gt;Link text&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="reference-style-link"&gt;&lt;a href="#reference-style-link" class="header-anchor"&gt;&lt;/a&gt;Reference Style Link
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://example.com" title="Link description"
 target="_blank" rel="noopener"
 &gt;Link text&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="article-reference"&gt;&lt;a href="#article-reference" class="header-anchor"&gt;&lt;/a&gt;Article Reference
&lt;/h3&gt;&lt;a class="stack-article-card" href="https://0andwild.com/docs/welcome/"&gt;
 &lt;span class="stack-article-card__title"&gt;/docs/welcome/&lt;/span&gt;&lt;span&gt;Open linked article&lt;/span&gt;&lt;/a&gt;

&lt;hr&gt;
&lt;h2 id="lists"&gt;&lt;a href="#lists" class="header-anchor"&gt;&lt;/a&gt;Lists
&lt;/h2&gt;&lt;h3 id="unordered-list"&gt;&lt;a href="#unordered-list" class="header-anchor"&gt;&lt;/a&gt;Unordered List
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Item 1&lt;/li&gt;
&lt;li&gt;Item 2
&lt;ul&gt;
&lt;li&gt;Sub-item 2-1&lt;/li&gt;
&lt;li&gt;Sub-item 2-2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Item 3&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ordered-list"&gt;&lt;a href="#ordered-list" class="header-anchor"&gt;&lt;/a&gt;Ordered List
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;First&lt;/li&gt;
&lt;li&gt;Second&lt;/li&gt;
&lt;li&gt;Third&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="checklist"&gt;&lt;a href="#checklist" class="header-anchor"&gt;&lt;/a&gt;Checklist
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Todo 1&lt;/li&gt;
&lt;li&gt;&lt;input checked="" disabled="" type="checkbox"&gt; Completed&lt;/li&gt;
&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Todo 2&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="blockquote"&gt;&lt;a href="#blockquote" class="header-anchor"&gt;&lt;/a&gt;Blockquote
&lt;/h2&gt;
 &lt;blockquote&gt;
 &lt;p&gt;This is a blockquote.
Multiple lines are supported.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="table"&gt;&lt;a href="#table" class="header-anchor"&gt;&lt;/a&gt;Table
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Item&lt;/th&gt;
					&lt;th&gt;Description&lt;/th&gt;
					&lt;th&gt;Note&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;A&lt;/td&gt;
					&lt;td&gt;Description A&lt;/td&gt;
					&lt;td&gt;Note A&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;B&lt;/td&gt;
					&lt;td&gt;Description B&lt;/td&gt;
					&lt;td&gt;Note B&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="embedded-links-shortcodes"&gt;&lt;a href="#embedded-links-shortcodes" class="header-anchor"&gt;&lt;/a&gt;Embedded Links (Shortcodes)
&lt;/h2&gt;&lt;h3 id="youtube-video"&gt;&lt;a href="#youtube-video" class="header-anchor"&gt;&lt;/a&gt;YouTube Video
&lt;/h3&gt;&lt;p&gt;{{&amp;lt; youtube VIDEO_ID &amp;gt;}}&lt;/p&gt;
&lt;h3 id="twitterx"&gt;&lt;a href="#twitterx" class="header-anchor"&gt;&lt;/a&gt;Twitter/X
&lt;/h3&gt;&lt;p&gt;{{&amp;lt; twitter user=&amp;ldquo;username&amp;rdquo; id=&amp;ldquo;tweet_id&amp;rdquo; &amp;gt;}}&lt;/p&gt;
&lt;h3 id="github-gist"&gt;&lt;a href="#github-gist" class="header-anchor"&gt;&lt;/a&gt;GitHub Gist
&lt;/h3&gt;&lt;p&gt;{{&amp;lt; gist username gist_id &amp;gt;}}&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="alert-boxes-blowfish-alert"&gt;&lt;a href="#alert-boxes-blowfish-alert" class="header-anchor"&gt;&lt;/a&gt;Alert Boxes (Blowfish Alert)
&lt;/h2&gt;&lt;p&gt;{{&amp;lt; alert &amp;ldquo;circle-info&amp;rdquo; &amp;gt;}}
Information alert.
{{&amp;lt; /alert &amp;gt;}}&lt;/p&gt;
&lt;p&gt;{{&amp;lt; alert &amp;ldquo;lightbulb&amp;rdquo; &amp;gt;}}
Tips and ideas.
{{&amp;lt; /alert &amp;gt;}}&lt;/p&gt;
&lt;p&gt;{{&amp;lt; alert &amp;ldquo;triangle-exclamation&amp;rdquo; &amp;gt;}}
Warning message.
{{&amp;lt; /alert &amp;gt;}}&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="collapsible-details"&gt;&lt;a href="#collapsible-details" class="header-anchor"&gt;&lt;/a&gt;Collapsible (Details)
&lt;/h2&gt;&lt;details&gt;
&lt;summary&gt;Click to expand&lt;/summary&gt;
&lt;p&gt;Hidden content appears here.&lt;/p&gt;
&lt;/details&gt;
&lt;hr&gt;
&lt;h2 id="comments"&gt;&lt;a href="#comments" class="header-anchor"&gt;&lt;/a&gt;Comments
&lt;/h2&gt;&lt;!-- This part is not displayed on screen --&gt;
&lt;hr&gt;
&lt;h2 id="horizontal-rule"&gt;&lt;a href="#horizontal-rule" class="header-anchor"&gt;&lt;/a&gt;Horizontal Rule
&lt;/h2&gt;&lt;p&gt;Use to create dividing lines:&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="footnotes"&gt;&lt;a href="#footnotes" class="header-anchor"&gt;&lt;/a&gt;Footnotes
&lt;/h2&gt;&lt;p&gt;You can add footnotes&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; to text.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="chart"&gt;&lt;a href="#chart" class="header-anchor"&gt;&lt;/a&gt;Chart
&lt;/h3&gt;&lt;div class="stack-chart"&gt;
 &lt;canvas id="stack-chart-3"&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/chart.js"&gt;&lt;/script&gt;
&lt;script&gt;
 (function () {
 const ctx = document.getElementById("stack-chart-3");
 if (!ctx || typeof Chart === "undefined") return;
 new Chart(ctx, { 
type: 'bar',
data: {
 labels: ['Tomato', 'Blueberry', 'Banana', 'Lime', 'Orange'],
 datasets: [{
 label: '# of votes',
 data: [12, 19, 3, 5, 3],
 }]
}
 });
 })();
&lt;/script&gt;

&lt;hr&gt;
&lt;h3 id="mermaid-diagram"&gt;&lt;a href="#mermaid-diagram" class="header-anchor"&gt;&lt;/a&gt;Mermaid Diagram
&lt;/h3&gt;&lt;pre class="mermaid" style="visibility:hidden"&gt;
graph LR;
A[Lemons]--&gt;B[Lemonade];
B--&gt;C[Profit]
&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id="swatches-color-showcase"&gt;&lt;a href="#swatches-color-showcase" class="header-anchor"&gt;&lt;/a&gt;Swatches (color showcase)
&lt;/h3&gt;&lt;div class="stack-swatch-grid"&gt;&lt;div class="stack-swatch" style="background: #64748b;"&gt;
 &lt;span&gt;#64748b&lt;/span&gt;
 &lt;/div&gt;&lt;div class="stack-swatch" style="background: #3b82f6;"&gt;
 &lt;span&gt;#3b82f6&lt;/span&gt;
 &lt;/div&gt;&lt;div class="stack-swatch" style="background: #06b6d4;"&gt;
 &lt;span&gt;#06b6d4&lt;/span&gt;
 &lt;/div&gt;&lt;/div&gt;

&lt;hr&gt;
&lt;h3 id="typeit"&gt;&lt;a href="#typeit" class="header-anchor"&gt;&lt;/a&gt;TypeIt
&lt;/h3&gt;&lt;p&gt;(Ex1)&lt;/p&gt;
&amp;lt;p id="stack-typeit-6" class="stack-typeit stack-typeit-cursor"&gt;&amp;lt;/p&gt;
&lt;script&gt;
 (function () {
 const target = document.getElementById("stack-typeit-6");
 if (!target) return;

 const lines = "[\"Lorem ipsum dolor sit amet\"]";
 const speed = "65";
 const shouldLoop = false;
 let lineIndex = 0;
 let charIndex = 0;
 let deleting = false;

 function tick() {
 const line = lines[lineIndex] || "";
 if (!deleting) {
 target.textContent = line.slice(0, charIndex + 1);
 charIndex += 1;
 if (charIndex === line.length) {
 deleting = true;
 setTimeout(tick, 1200);
 return;
 }
 } else {
 target.textContent = line.slice(0, Math.max(charIndex - 1, 0));
 charIndex -= 1;
 if (charIndex &lt;= 0) {
 deleting = false;
 lineIndex = (lineIndex + 1) % lines.length;
 if (!shouldLoop &amp;&amp; lineIndex === 0) {
 target.textContent = lines[lines.length - 1] || "";
 target.classList.remove("stack-typeit-cursor");
 return;
 }
 }
 }
 setTimeout(tick, deleting ? speed / 2 : speed);
 }

 tick();
 })();
&lt;/script&gt;

&lt;p&gt;(Ex2)&lt;/p&gt;
&amp;lt;h1 id="stack-typeit-7" class="stack-typeit stack-typeit-cursor"&gt;&amp;lt;/h1&gt;
&lt;script&gt;
 (function () {
 const target = document.getElementById("stack-typeit-7");
 if (!target) return;

 const lines = "[\"Lorem ipsum dolor sit amet,\",\"consectetur adipiscing elit.\"]";
 const speed = "65";
 const shouldLoop = false;
 let lineIndex = 0;
 let charIndex = 0;
 let deleting = false;

 function tick() {
 const line = lines[lineIndex] || "";
 if (!deleting) {
 target.textContent = line.slice(0, charIndex + 1);
 charIndex += 1;
 if (charIndex === line.length) {
 deleting = true;
 setTimeout(tick, 1200);
 return;
 }
 } else {
 target.textContent = line.slice(0, Math.max(charIndex - 1, 0));
 charIndex -= 1;
 if (charIndex &lt;= 0) {
 deleting = false;
 lineIndex = (lineIndex + 1) % lines.length;
 if (!shouldLoop &amp;&amp; lineIndex === 0) {
 target.textContent = lines[lines.length - 1] || "";
 target.classList.remove("stack-typeit-cursor");
 return;
 }
 }
 }
 setTimeout(tick, deleting ? speed / 2 : speed);
 }

 tick();
 })();
&lt;/script&gt;

&lt;p&gt;(Ex3)&lt;/p&gt;
&amp;lt;h3 id="stack-typeit-8" class="stack-typeit stack-typeit-cursor"&gt;&amp;lt;/h3&gt;
&lt;script&gt;
 (function () {
 const target = document.getElementById("stack-typeit-8");
 if (!target) return;

 const lines = "[\"\\\"Frankly, my dear, I don't give a damn.\\\" Gone with the Wind (1939)\",\"\\\"I'm gonna make him an offer he can't refuse.\\\" The Godfather (1972)\",\"\\\"Toto, I've a feeling we're not in Kansas anymore.\\\" The Wizard of Oz (1939)\"]";
 const speed = 50 ;
 const shouldLoop = false;
 let lineIndex = 0;
 let charIndex = 0;
 let deleting = false;

 function tick() {
 const line = lines[lineIndex] || "";
 if (!deleting) {
 target.textContent = line.slice(0, charIndex + 1);
 charIndex += 1;
 if (charIndex === line.length) {
 deleting = true;
 setTimeout(tick, 1200);
 return;
 }
 } else {
 target.textContent = line.slice(0, Math.max(charIndex - 1, 0));
 charIndex -= 1;
 if (charIndex &lt;= 0) {
 deleting = false;
 lineIndex = (lineIndex + 1) % lines.length;
 if (!shouldLoop &amp;&amp; lineIndex === 0) {
 target.textContent = lines[lines.length - 1] || "";
 target.classList.remove("stack-typeit-cursor");
 return;
 }
 }
 }
 setTimeout(tick, deleting ? speed / 2 : speed);
 }

 tick();
 })();
&lt;/script&gt;

&lt;hr&gt;
&lt;h3 id="youtube-lite"&gt;&lt;a href="#youtube-lite" class="header-anchor"&gt;&lt;/a&gt;Youtube Lite
&lt;/h3&gt;&lt;div class="stack-youtube-lite"&gt;
 &lt;iframe
 src="https://www.youtube.com/embed/SgXhGb-7QbU"
 title="Blowfish-tools demo"
 loading="lazy"
 allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
 referrerpolicy="strict-origin-when-cross-origin"
 allowfullscreen&gt;
 &lt;/iframe&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Writing Tips:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Change &lt;code&gt;draft: true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; in front matter to publish&lt;/li&gt;
&lt;li&gt;Writing &lt;code&gt;description&lt;/code&gt; and &lt;code&gt;summary&lt;/code&gt; helps with SEO&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s recommended to place images in the post folder&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;This is the footnote content.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Why I Switched to Hugo &amp; GitHub Pages</title><link>https://0andwild.com/en/posts/251015_about_hugo/</link><pubDate>Wed, 15 Oct 2025 17:21:09 +0900</pubDate><guid>https://0andwild.com/en/posts/251015_about_hugo/</guid><description>&lt;img src="https://0andwild.com/" alt="Featured image of post Why I Switched to Hugo &amp; GitHub Pages" /&gt;&lt;h2 id="why-i-moved-to-hugo--github-pages"&gt;&lt;a href="#why-i-moved-to-hugo--github-pages" class="header-anchor"&gt;&lt;/a&gt;Why I Moved to Hugo &amp;amp; GitHub Pages
&lt;/h2&gt;&lt;p&gt;I decided to migrate my tech blog from &lt;a class="link" href="https://0andwild.tistory.com/" target="_blank" rel="noopener"
 &gt;&lt;strong&gt;Tstory&lt;/strong&gt;&lt;/a&gt; to &lt;strong&gt;Hugo &amp;amp; GitHub Pages&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="1-scattered-content-management"&gt;&lt;a href="#1-scattered-content-management" class="header-anchor"&gt;&lt;/a&gt;1. Scattered Content Management
&lt;/h3&gt;&lt;p&gt;As I used various note-taking tools, the content I wrote at work or while studying became scattered everywhere. Having to transfer these notes to the blog repeatedly became burdensome, which led me to neglect blog management.&lt;/p&gt;
&lt;h3 id="2-markdown-compatibility-issues"&gt;&lt;a href="#2-markdown-compatibility-issues" class="header-anchor"&gt;&lt;/a&gt;2. Markdown Compatibility Issues
&lt;/h3&gt;&lt;p&gt;The markdown syntax used in my note-taking tools wasn&amp;rsquo;t fully compatible with Tstory, requiring frequent modifications when publishing posts. This was also a source of frustration.&lt;/p&gt;
&lt;p&gt;Specific issues included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Insufficient syntax highlighting support for code blocks&lt;/li&gt;
&lt;li&gt;Table rendering errors&lt;/li&gt;
&lt;li&gt;Image path handling problems&lt;/li&gt;
&lt;li&gt;Limited mathematical expression support&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="3-tstory-open-api-support-ended"&gt;&lt;a href="#3-tstory-open-api-support-ended" class="header-anchor"&gt;&lt;/a&gt;3. Tstory Open API Support Ended
&lt;/h3&gt;&lt;p&gt;Recently, I wanted to reorganize my study materials and post them on Tstory while redesigning the blog skin. I also planned to integrate existing note-taking tools using the &lt;strong&gt;Tstory Official Open API&lt;/strong&gt;. However, I discovered that Open API support had been discontinued, and there was no longer a reason to continue using Tstory.&lt;/p&gt;
&lt;h3 id="blog-platform-selection-criteria"&gt;&lt;a href="#blog-platform-selection-criteria" class="header-anchor"&gt;&lt;/a&gt;Blog Platform Selection Criteria
&lt;/h3&gt;&lt;p&gt;After researching various blogs and considering what approach would work best, I settled on &lt;strong&gt;Hugo &amp;amp; GitHub Pages&lt;/strong&gt; based on the following criteria:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Is it easy to set up the blog?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can it be managed with code?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is there high flexibility to add features I want?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is the build and deployment speed fast when using GitHub Pages?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is it easy to integrate with note-taking tools like Obsidian?&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="what-is-hugo"&gt;&lt;a href="#what-is-hugo" class="header-anchor"&gt;&lt;/a&gt;What is Hugo?
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener"
 &gt;&lt;strong&gt;Hugo&lt;/strong&gt;&lt;/a&gt; is a fast and flexible &lt;strong&gt;Static Site Generator&lt;/strong&gt; written in the &lt;strong&gt;Go language&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast build speed&lt;/strong&gt;: Thousands of pages can be built in seconds&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple structure&lt;/strong&gt;: Write content in Markdown and Hugo converts it to HTML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero dependencies&lt;/strong&gt;: Runs as a single binary without requiring separate runtime or database&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rich theme ecosystem&lt;/strong&gt;: Easy to apply themes for various purposes&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="comparing-static-site-generators-used-with-github-pages"&gt;&lt;a href="#comparing-static-site-generators-used-with-github-pages" class="header-anchor"&gt;&lt;/a&gt;Comparing Static Site Generators Used with GitHub Pages
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Feature&lt;/th&gt;
					&lt;th&gt;Hugo&lt;/th&gt;
					&lt;th&gt;Jekyll&lt;/th&gt;
					&lt;th&gt;Gatsby&lt;/th&gt;
					&lt;th&gt;Next.js (SSG)&lt;/th&gt;
					&lt;th&gt;VuePress&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Language&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Go&lt;/td&gt;
					&lt;td&gt;Ruby&lt;/td&gt;
					&lt;td&gt;React (JavaScript)&lt;/td&gt;
					&lt;td&gt;React (JavaScript)&lt;/td&gt;
					&lt;td&gt;Vue.js&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Build Speed&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;⚡ Very Fast (&amp;lt; 1ms/page)&lt;/td&gt;
					&lt;td&gt;🐢 Slow&lt;/td&gt;
					&lt;td&gt;🚶 Moderate&lt;/td&gt;
					&lt;td&gt;🚶 Moderate&lt;/td&gt;
					&lt;td&gt;🚶 Moderate&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Installation Complexity&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;✅ Single Binary&lt;/td&gt;
					&lt;td&gt;⚠️ Ruby environment required&lt;/td&gt;
					&lt;td&gt;⚠️ Node.js + many dependencies&lt;/td&gt;
					&lt;td&gt;⚠️ Node.js + dependencies&lt;/td&gt;
					&lt;td&gt;⚠️ Node.js + dependencies&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;GitHub Pages Native Support&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;❌ (Actions required)&lt;/td&gt;
					&lt;td&gt;✅ Native support&lt;/td&gt;
					&lt;td&gt;❌ (Actions required)&lt;/td&gt;
					&lt;td&gt;❌ (Actions required)&lt;/td&gt;
					&lt;td&gt;❌ (Actions required)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
					&lt;td&gt;Low&lt;/td&gt;
					&lt;td&gt;High&lt;/td&gt;
					&lt;td&gt;Medium-High&lt;/td&gt;
					&lt;td&gt;Medium&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Themes/Plugins&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Rich&lt;/td&gt;
					&lt;td&gt;Very Rich&lt;/td&gt;
					&lt;td&gt;Rich (React ecosystem)&lt;/td&gt;
					&lt;td&gt;Rich (React ecosystem)&lt;/td&gt;
					&lt;td&gt;Moderate&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Best For&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Blog, Docs, Portfolio&lt;/td&gt;
					&lt;td&gt;Blog, GitHub default&lt;/td&gt;
					&lt;td&gt;Complex web apps, Blog&lt;/td&gt;
					&lt;td&gt;Complex web apps, Hybrid&lt;/td&gt;
					&lt;td&gt;Technical docs&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;Build Time (1000 pages)&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;~1s&lt;/td&gt;
					&lt;td&gt;~2min&lt;/td&gt;
					&lt;td&gt;~30s&lt;/td&gt;
					&lt;td&gt;~30s&lt;/td&gt;
					&lt;td&gt;~20s&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Why I Chose Hugo:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Overwhelming build speed&lt;/strong&gt;: Build time barely increases even with more content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple setup&lt;/strong&gt;: Focus on Markdown without complex JavaScript frameworks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero dependencies&lt;/strong&gt;: No environment setup issues with a single executable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rich themes&lt;/strong&gt;: Easy to apply high-quality themes like Blowfish&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="github-pages-deployment"&gt;&lt;a href="#github-pages-deployment" class="header-anchor"&gt;&lt;/a&gt;GitHub Pages Deployment
&lt;/h2&gt;&lt;p&gt;Blogs written with Hugo are automatically built and deployed through &lt;strong&gt;GitHub Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="deployment-workflow"&gt;&lt;a href="#deployment-workflow" class="header-anchor"&gt;&lt;/a&gt;Deployment Workflow
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Push changes to the &lt;code&gt;main&lt;/code&gt; branch&lt;/li&gt;
&lt;li&gt;GitHub Actions automatically triggers&lt;/li&gt;
&lt;li&gt;Hugo builds the static site&lt;/li&gt;
&lt;li&gt;Built files are automatically deployed to GitHub Pages&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="benefits"&gt;&lt;a href="#benefits" class="header-anchor"&gt;&lt;/a&gt;Benefits
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automated deployment&lt;/strong&gt;: Automatically deploys when you push code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version control&lt;/strong&gt;: Track all changes through Git&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free hosting&lt;/strong&gt;: GitHub Pages is provided for free&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom domain&lt;/strong&gt;: Can connect your desired domain&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTPS support&lt;/strong&gt;: HTTPS is provided by default&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="obsidian-integration"&gt;&lt;a href="#obsidian-integration" class="header-anchor"&gt;&lt;/a&gt;Obsidian Integration
&lt;/h2&gt;&lt;p&gt;Hugo is markdown-based, making it perfectly compatible with note-taking tools like &lt;strong&gt;Obsidian&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="integration-method"&gt;&lt;a href="#integration-method" class="header-anchor"&gt;&lt;/a&gt;Integration Method
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Set Hugo blog&amp;rsquo;s &lt;code&gt;content/posts&lt;/code&gt; directory as Obsidian vault&lt;/li&gt;
&lt;li&gt;Write and edit posts in Obsidian&lt;/li&gt;
&lt;li&gt;When finished writing, commit &amp;amp; push through Git&lt;/li&gt;
&lt;li&gt;GitHub Actions automatically builds and deploys&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="benefits-1"&gt;&lt;a href="#benefits-1" class="header-anchor"&gt;&lt;/a&gt;Benefits
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistent writing environment&lt;/strong&gt;: Manage all notes and blog posts in the same tool&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Perfect markdown compatibility&lt;/strong&gt;: No additional conversion work needed&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local-first&lt;/strong&gt;: Can write posts without internet connection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Powerful linking features&lt;/strong&gt;: Utilize Obsidian&amp;rsquo;s backlinks and graph view&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="terminal-commands"&gt;&lt;a href="#terminal-commands" class="header-anchor"&gt;&lt;/a&gt;Terminal Commands
&lt;/h2&gt;&lt;h3 id="running-development-server"&gt;&lt;a href="#running-development-server" class="header-anchor"&gt;&lt;/a&gt;Running Development Server
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Starts a local development server. By default, you can view the site at &lt;code&gt;http://localhost:1313&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Options:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-D&lt;/code&gt; or &lt;code&gt;--buildDrafts&lt;/code&gt;: Builds draft content as well&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--bind 0.0.0.0&lt;/code&gt;: Makes server accessible from all network interfaces&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--port 8080&lt;/code&gt;: Uses a different port instead of the default (1313)&lt;/li&gt;
&lt;li&gt;Browser automatically refreshes when files change (Live Reload)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server -D
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo server --bind 0.0.0.0 --port &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="production-build"&gt;&lt;a href="#production-build" class="header-anchor"&gt;&lt;/a&gt;Production Build
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo --cleanDestinationDir
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Builds the static site for production. Output is generated in the &lt;code&gt;public/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--cleanDestinationDir&lt;/code&gt;: Completely cleans the destination directory (&lt;code&gt;public/&lt;/code&gt;) before building&lt;/li&gt;
&lt;li&gt;Removes unnecessary files from previous builds for a clean build&lt;/li&gt;
&lt;li&gt;Ensures no old versions of files remain even when filenames are changed or deleted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo --cleanDestinationDir
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;hugo --cleanDestinationDir --minify &lt;span class="c1"&gt;# Add file minification option&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="theme-information"&gt;&lt;a href="#theme-information" class="header-anchor"&gt;&lt;/a&gt;Theme Information
&lt;/h2&gt;&lt;h3 id="hugo-blowfish-theme"&gt;&lt;a href="#hugo-blowfish-theme" class="header-anchor"&gt;&lt;/a&gt;Hugo Blowfish Theme
&lt;/h3&gt;&lt;p&gt;This blog uses the &lt;a class="link" href="https://blowfish.page/" target="_blank" rel="noopener"
 &gt;&lt;strong&gt;Blowfish&lt;/strong&gt;&lt;/a&gt; theme.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provides modern and responsive design&lt;/li&gt;
&lt;li&gt;Supports dark mode&lt;/li&gt;
&lt;li&gt;Fast loading speed and SEO optimized&lt;/li&gt;
&lt;li&gt;Multilingual support&lt;/li&gt;
&lt;li&gt;Rich customization options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Configuration Files:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;config/_default/hugo.toml&lt;/code&gt; - Basic Hugo configuration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/_default/params.toml&lt;/code&gt; - Blowfish theme parameters&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/_default/languages.en.toml&lt;/code&gt; - Language-specific settings&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config/_default/menus.en.toml&lt;/code&gt; - Menu configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;&lt;a href="#conclusion" class="header-anchor"&gt;&lt;/a&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;The migration from Tstory to Hugo &amp;amp; GitHub Pages was a choice for a developer-friendly environment. Now I can manage my blog the same way I manage code versions, and with perfect Obsidian integration, I&amp;rsquo;ve unified the workflow from note-taking to blog posting.&lt;/p&gt;
&lt;p&gt;Above all, Hugo&amp;rsquo;s fast build speed and GitHub Actions&amp;rsquo; automated deployment allow me to focus solely on writing, and I can freely customize without being bound by platform constraints.&lt;/p&gt;
&lt;p&gt;Going forward, I plan to gradually migrate existing posts from Tstory while steadily adding new content.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="references"&gt;&lt;a href="#references" class="header-anchor"&gt;&lt;/a&gt;References
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hugo Official Site:&lt;/strong&gt; &lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener"
 &gt;https://gohugo.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blowfish Theme:&lt;/strong&gt; &lt;a class="link" href="https://blowfish.page/" target="_blank" rel="noopener"
 &gt;https://blowfish.page/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blowfish Creator:&lt;/strong&gt; &lt;a class="link" href="https://github.com/nunocoracao" target="_blank" rel="noopener"
 &gt;@nunocoracao&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creator Blog:&lt;/strong&gt; &lt;a class="link" href="https://n9o.xyz/" target="_blank" rel="noopener"
 &gt;https://n9o.xyz/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Official Docs:&lt;/strong&gt; &lt;a class="link" href="https://blowfish.page/docs/" target="_blank" rel="noopener"
 &gt;https://blowfish.page/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;License:&lt;/strong&gt; &lt;a class="link" href="https://en.wikipedia.org/wiki/MIT_License" target="_blank" rel="noopener"
 &gt;MIT License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>