<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>cusdis &amp;mdash; Blog - Kais BETTAIEB</title>
    <link>https://blog.kaisbettaieb.dev/tag:cusdis</link>
    <description>Python Developer crafting robust applications at the intersection of design, technology, and user experience.</description>
    <pubDate>Tue, 28 Apr 2026 11:06:56 +0000</pubDate>
    <item>
      <title>Adding Comments to WriteFreely with Cusdis</title>
      <link>https://blog.kaisbettaieb.dev/adding-comments-to-writefreely-with-cusdis</link>
      <description>&lt;![CDATA[#cusdis #comments #writefreely #javascript &#xA;&#xA;WriteFreely is beloved for its minimalism. However, fostering a community often requires a feedback loop. The challenge is adding comments without shattering that clean, distraction-free aesthetic.&#xA;!--more--&#xA;I recently integrated Cusdis—a lightweight, open-source, and privacy-friendly comment system—into this blog. It aligns seamlessly with WriteFreely’s ethos: it requires no user tracking and adapts beautifully with a bit of custom CSS.&#xA;&#xA;Here is how to implement a fully dynamic, styled comment section. This script ensures the widget loads only on individual posts (keeping your homepage pristine) and automatically respects dark mode.&#xA;&#xA;Step 1: Get Your Cusdis ID&#xA;&#xA;First, you need a running Cusdis instance. You have two paths:&#xA;&#xA;Cloud: Create a free account at Cusdis.com.&#xA;Self-Hosted: Host it yourself on a VPS (using Coolify or Docker) for 100% data ownership.&#xA;&#xA;Once you have access to your dashboard, copy your App ID (e.g., f42fd160-a4f2-...). You will need this for the JavaScript configuration below.&#xA;&#xA;Step 2: The Logic (Why Custom JS?)&#xA;&#xA;Since WriteFreely lacks native support for editing individual post templates, we cannot simply paste the standard Cusdis embed code. A static embed cannot automatically fetch the unique Page ID or Title for every article.&#xA;&#xA;Instead, we use Custom JavaScript to:&#xA;&#xA;Verify context: Check if the user is viewing a single post (ignoring the homepage).&#xA;Build the UI: Dynamically append a &#34;Comments&#34; container to the bottom of the article.&#xA;Inject the Widget: Initialize Cusdis with the correct metadata (ID, URL, Title).&#xA;Style: Force the widget into &#34;Dark Mode&#34; to match the theme.&#xA;&#xA;Step 3: The JavaScript Code&#xA;&#xA;Navigate to your WriteFreely dashboard, go to Customize   Custom JavaScript, and paste the code below.&#xA;&#xA;  Note: Be sure to replace &#39;YOUR-APP-ID-HERE&#39; with the actual ID you copied in Step 1.&#xA;&#xA;(function() {&#xA;    // Only run this script if we are on a post page (body#post)&#xA;    // This prevents the comments from loading on the homepage or collections.&#xA;    var postBody = document.querySelector(&#39;body#post&#39;);&#xA;    &#xA;    if (postBody) {&#xA;        // 1. Create the container div for Cusdis&#xA;        var cusdisContainer = document.createElement(&#39;div&#39;);&#xA;        cusdisContainer.id = &#39;cusdisthread&#39;;&#xA;        cusdisContainer.dataset.host = &#39;https://cusdis.com&#39;;&#xA;        cusdisContainer.dataset.appId = &#39;YOUR-APP-ID-HERE&#39;; // PASTE YOUR ID HERE&#xA;        cusdisContainer.dataset.pageId = window.location.pathname;&#xA;        cusdisContainer.dataset.pageUrl = window.location.href;&#xA;        cusdisContainer.dataset.pageTitle = document.title;&#xA;        cusdisContainer.dataset.theme = &#39;dark&#39;; // Forces dark mode&#xA;&#xA;        // 2. Append the container to the article or main content area&#xA;        // Note: &#39;article&#39; is standard in most WriteFreely themes. &#xA;        var article = document.querySelector(&#39;article&#39;);&#xA;        if (article) {&#xA;            article.appendChild(cusdisContainer);&#xA;        }&#xA;&#xA;        // 3. Load the Cusdis SDK asynchronously&#xA;        var script = document.createElement(&#39;script&#39;);&#xA;        script.src = &#39;https://cusdis.com/js/cusdis.es.js&#39;;&#xA;        script.async = true;&#xA;        script.defer = true;&#xA;        document.body.appendChild(script);&#xA;    }&#xA;})();&#xA;&#xA;Step 4: The styling&#xA;&#xA;Now that the functionality is in place, let&#39;s style the container to look like a piece of retro-futuristic hardware. We want a monospace font, a &#34;console&#34; border, and a distinct separation from the rest of your content.&#xA;&#xA;Navigate to Customize   Custom CSS and add the following:&#xA;&#xA;/ --- VISIBILITY RULES of COMMENT SECTION --- /&#xA;body#collection #comment-section,&#xA;body#subpage #comment-section {&#xA;    display: none !important;&#xA;}&#xA;&#xA;body#post #comment-section {&#xA;    display: block !important;&#xA;}&#xA;&#xA;/ --- END VISIBILITY RULES OF COMMENT SECTION -- /&#xA;/ --- CUSDIS COMMENT SECTION FIXES --- /&#xA;comment-section {&#xA;    margin-top: 3rem; / space from article content /&#xA;    width: 100%;&#xA;    max-width: 100%;&#xA;}&#xA;&#xA;/ Cusdis iframe container /&#xA;cusdisthread {&#xA;    width: 100% !important;&#xA;    min-height: 500px; / initial height /&#xA;    border-radius: 8px;&#xA;    overflow: hidden; / remove inner scrollbars /&#xA;    background-color: var(--surface-color) !important;&#xA;    border: 1px solid var(--border-color) !important;&#xA;    box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);&#xA;}&#xA;&#xA;/ Make the iframe responsive /&#xA;cusdisthread iframe {&#xA;    width: 100% !important;&#xA;    min-height: 500px !important;&#xA;    height: auto !important;&#xA;    border: none !important;&#xA;}&#xA;&#xA;/ Dark theme for Cusdis content /&#xA;cusdisthread {&#xA;    --cusdis-background: var(--surface-color);&#xA;    --cusdis-text-color: var(--text-color);&#xA;    --cusdis-accent-color: var(--accent-color);&#xA;    --cusdis-border-color: var(--border-color);&#xA;    --cusdis-input-background: #222; / input background /&#xA;    --cusdis-input-text-color: #eee; / input text /&#xA;    --cusdis-button-background: var(--accent-color);&#xA;    --cusdis-button-text-color: #000;&#xA;}&#xA;&#xA;/ Force Cusdis to expand to fit content (if Cusdis JS supports it) /&#xA;cusdisthread iframe {&#xA;    height: 100% !important;&#xA;}&#xA;&#xA;/ Inputs and textareas /&#xA;cusdisthread textarea,&#xA;cusdisthread input {&#xA;    background-color: #222 !important;&#xA;    color: #eee !important;&#xA;    border: 1px solid var(--border-color) !important;&#xA;    border-radius: 6px;&#xA;    padding: 8px;&#xA;}&#xA;&#xA;/ Submit button /&#xA;cusdisthread button {&#xA;    background-color: var(--accent-color) !important;&#xA;    color: #000 !important;&#xA;    font-weight: 700;&#xA;    border-radius: 6px !important;&#xA;    padding: 6px 14px !important;&#xA;    border: none !important;&#xA;    cursor: pointer;&#xA;    transition: all 0.2s ease;&#xA;}&#xA;&#xA;cusdisthread button:hover {&#xA;    background-color: #3aa8d1 !important;&#xA;    box-shadow: 0 0 12px rgba(98, 200, 243, 0.5) !important;&#xA;    color: #000 !important;&#xA;}&#xA;&#xA;/ Scrollbar styling for iframe if it still scrolls /&#xA;cusdisthread iframe::-webkit-scrollbar {&#xA;    width: 8px;&#xA;}&#xA;&#xA;cusdisthread iframe::-webkit-scrollbar-thumb {&#xA;    background-color: #555;&#xA;    border-radius: 4px;&#xA;}&#xA;&#xA;cusdisthread iframe::-webkit-scrollbar-track {&#xA;    background-color: #111;&#xA;}&#xA;&#xA;/ Optional: smooth font for Cusdis /&#xA;cusdisthread,&#xA;cusdisthread iframe {&#xA;    font-family: &#39;Nunito&#39;, sans-serif !important;&#xA;}&#xA;&#xA;Final Thoughts&#xA;&#xA;And that is it. You now have a lightweight, privacy-respecting comment section that loads exclusively on your articles.&#xA;&#xA;By injecting the widget via JavaScript, you bypass WriteFreely&#39;s template limitations while maintaining total control over the look and feel. Your readers can now interact with your content in a space that feels like a natural extension of your blog&#39;s &#34;hacker&#34; aesthetic—no tracking pixels attached.&#xA;&#xA;div class=&#34;blog-signature&#34;&#xD;&#xA;    div class=&#34;sig-content&#34;&#xD;&#xA;        pThanks for reading! If you found this helpful:/p&#xD;&#xA;        div class=&#34;sig-links&#34;&#xD;&#xA;            a href=&#34;https://ko-fi.com/kaisbettaieb&#34; class=&#34;kofi-btn&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;☕ Buy me a coffee/a&#xD;&#xA;            span class=&#34;divider&#34;or/span&#xD;&#xA;            a href=&#34;https://github.com/kaisbettaieb&#34; class=&#34;text-link&#34;Check my Code/a&#xD;&#xA;            span class=&#34;divider&#34;or/span&#xD;&#xA;            a href=&#34;https://kbt.dev&#34; class=&#34;text-link&#34;More about me/a&#xD;&#xA;        /div&#xD;&#xA;    /div&#xD;&#xA;/div&#xD;&#xA;div id=&#34;comment-section&#34;/div&#xD;&#xA;&#xD;&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://blog.kaisbettaieb.dev/tag:cusdis" class="hashtag"><span>#</span><span class="p-category">cusdis</span></a> <a href="https://blog.kaisbettaieb.dev/tag:comments" class="hashtag"><span>#</span><span class="p-category">comments</span></a> <a href="https://blog.kaisbettaieb.dev/tag:writefreely" class="hashtag"><span>#</span><span class="p-category">writefreely</span></a> <a href="https://blog.kaisbettaieb.dev/tag:javascript" class="hashtag"><span>#</span><span class="p-category">javascript</span></a></p>

<p>WriteFreely is beloved for its minimalism. However, fostering a community often requires a feedback loop. The challenge is adding comments without shattering that clean, distraction-free aesthetic.

I recently integrated <strong>Cusdis</strong>—a lightweight, open-source, and privacy-friendly comment system—into this blog. It aligns seamlessly with WriteFreely’s ethos: it requires no user tracking and adapts beautifully with a bit of custom CSS.</p>

<p>Here is how to implement a fully dynamic, styled comment section. This script ensures the widget loads <strong>only</strong> on individual posts (keeping your homepage pristine) and automatically respects dark mode.</p>

<h2 id="step-1-get-your-cusdis-id">Step 1: Get Your Cusdis ID</h2>

<p>First, you need a running Cusdis instance. You have two paths:</p>
<ul><li><strong>Cloud:</strong> Create a free account at <a href="https://cusdis.com">Cusdis.com</a>.</li>
<li><strong>Self-Hosted:</strong> Host it yourself on a VPS (using Coolify or Docker) for 100% data ownership.</li></ul>

<p>Once you have access to your dashboard, copy your <strong>App ID</strong> (e.g., <code>f42fd160-a4f2-...</code>). You will need this for the JavaScript configuration below.</p>

<h2 id="step-2-the-logic-why-custom-js">Step 2: The Logic (Why Custom JS?)</h2>

<p>Since WriteFreely lacks native support for editing individual post templates, we cannot simply paste the standard Cusdis embed code. A static embed cannot automatically fetch the unique Page ID or Title for every article.</p>

<p>Instead, we use Custom JavaScript to:</p>
<ol><li><strong>Verify context:</strong> Check if the user is viewing a single post (ignoring the homepage).</li>
<li><strong>Build the UI:</strong> Dynamically append a “Comments” container to the bottom of the article.</li>
<li><strong>Inject the Widget:</strong> Initialize Cusdis with the correct metadata (ID, URL, Title).</li>
<li><strong>Style:</strong> Force the widget into “Dark Mode” to match the theme.</li></ol>

<h2 id="step-3-the-javascript-code">Step 3: The JavaScript Code</h2>

<p>Navigate to your WriteFreely dashboard, go to <strong>Customize &gt; Custom JavaScript</strong>, and paste the code below.</p>

<blockquote><p><strong>Note:</strong> Be sure to replace <code>&#39;YOUR-APP-ID-HERE&#39;</code> with the actual ID you copied in Step 1.</p></blockquote>

<pre><code class="language-javascript">(function() {
    // Only run this script if we are on a post page (body#post)
    // This prevents the comments from loading on the homepage or collections.
    var postBody = document.querySelector(&#39;body#post&#39;);
    
    if (postBody) {
        // 1. Create the container div for Cusdis
        var cusdisContainer = document.createElement(&#39;div&#39;);
        cusdisContainer.id = &#39;cusdis_thread&#39;;
        cusdisContainer.dataset.host = &#39;[https://cusdis.com](https://cusdis.com)&#39;;
        cusdisContainer.dataset.appId = &#39;YOUR-APP-ID-HERE&#39;; // PASTE YOUR ID HERE
        cusdisContainer.dataset.pageId = window.location.pathname;
        cusdisContainer.dataset.pageUrl = window.location.href;
        cusdisContainer.dataset.pageTitle = document.title;
        cusdisContainer.dataset.theme = &#39;dark&#39;; // Forces dark mode

        // 2. Append the container to the article or main content area
        // Note: &#39;article&#39; is standard in most WriteFreely themes. 
        var article = document.querySelector(&#39;article&#39;);
        if (article) {
            article.appendChild(cusdisContainer);
        }

        // 3. Load the Cusdis SDK asynchronously
        var script = document.createElement(&#39;script&#39;);
        script.src = &#39;[https://cusdis.com/js/cusdis.es.js](https://cusdis.com/js/cusdis.es.js)&#39;;
        script.async = true;
        script.defer = true;
        document.body.appendChild(script);
    }
})();
</code></pre>

<h2 id="step-4-the-styling">Step 4: The styling</h2>

<p>Now that the functionality is in place, let&#39;s style the container to look like a piece of retro-futuristic hardware. We want a monospace font, a “console” border, and a distinct separation from the rest of your content.</p>

<p>Navigate to <strong>Customize &gt; Custom CSS</strong> and add the following:</p>

<pre><code class="language-css">
/* --- VISIBILITY RULES of COMMENT SECTION --- */
body#collection #comment-section,
body#subpage #comment-section {
    display: none !important;
}

body#post #comment-section {
    display: block !important;
}

/* --- END VISIBILITY RULES OF COMMENT SECTION -- */
/* --- CUSDIS COMMENT SECTION FIXES --- */
#comment-section {
    margin-top: 3rem; /* space from article content */
    width: 100%;
    max-width: 100%;
}

/* Cusdis iframe container */
#cusdis_thread {
    width: 100% !important;
    min-height: 500px; /* initial height */
    border-radius: 8px;
    overflow: hidden; /* remove inner scrollbars */
    background-color: var(--surface-color) !important;
    border: 1px solid var(--border-color) !important;
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.4);
}

/* Make the iframe responsive */
#cusdis_thread iframe {
    width: 100% !important;
    min-height: 500px !important;
    height: auto !important;
    border: none !important;
}

/* Dark theme for Cusdis content */
#cusdis_thread {
    --cusdis-background: var(--surface-color);
    --cusdis-text-color: var(--text-color);
    --cusdis-accent-color: var(--accent-color);
    --cusdis-border-color: var(--border-color);
    --cusdis-input-background: #222; /* input background */
    --cusdis-input-text-color: #eee; /* input text */
    --cusdis-button-background: var(--accent-color);
    --cusdis-button-text-color: #000;
}

/* Force Cusdis to expand to fit content (if Cusdis JS supports it) */
#cusdis_thread iframe {
    height: 100% !important;
}

/* Inputs and textareas */
#cusdis_thread textarea,
#cusdis_thread input {
    background-color: #222 !important;
    color: #eee !important;
    border: 1px solid var(--border-color) !important;
    border-radius: 6px;
    padding: 8px;
}

/* Submit button */
#cusdis_thread button {
    background-color: var(--accent-color) !important;
    color: #000 !important;
    font-weight: 700;
    border-radius: 6px !important;
    padding: 6px 14px !important;
    border: none !important;
    cursor: pointer;
    transition: all 0.2s ease;
}

#cusdis_thread button:hover {
    background-color: #3aa8d1 !important;
    box-shadow: 0 0 12px rgba(98, 200, 243, 0.5) !important;
    color: #000 !important;
}

/* Scrollbar styling for iframe if it still scrolls */
#cusdis_thread iframe::-webkit-scrollbar {
    width: 8px;
}

#cusdis_thread iframe::-webkit-scrollbar-thumb {
    background-color: #555;
    border-radius: 4px;
}

#cusdis_thread iframe::-webkit-scrollbar-track {
    background-color: #111;
}

/* Optional: smooth font for Cusdis */
#cusdis_thread,
#cusdis_thread iframe {
    font-family: &#39;Nunito&#39;, sans-serif !important;
}

</code></pre>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>And that is it. You now have a lightweight, privacy-respecting comment section that loads exclusively on your articles.</p>

<p>By injecting the widget via JavaScript, you bypass WriteFreely&#39;s template limitations while maintaining total control over the look and feel. Your readers can now interact with your content in a space that feels like a natural extension of your blog&#39;s “hacker” aesthetic—no tracking pixels attached.</p>

<div class="blog-signature">
    <div class="sig-content">
        <p>Thanks for reading! If you found this helpful:</p>
        <div class="sig-links">
            <a href="https://ko-fi.com/kaisbettaieb" class="kofi-btn" target="_blank">☕ Buy me a coffee</a>
            <span class="divider">or</span>
            <a href="https://github.com/kaisbettaieb" class="text-link">Check my Code</a>
            <span class="divider">or</span>
            <a href="https://kbt.dev" class="text-link">More about me</a>
        </div>
    </div>
</div>
<div id="comment-section"></div>
]]></content:encoded>
      <guid>https://blog.kaisbettaieb.dev/adding-comments-to-writefreely-with-cusdis</guid>
      <pubDate>Tue, 13 Jan 2026 14:51:59 +0000</pubDate>
    </item>
  </channel>
</rss>