# New features for my blog! Adding Comments + RSS to Hugo PaperMod (Giscus and Isso FTW)

A friendly, copy-pasteable guide to wiring up Giscus comments (GitHub Discussions) and Isso comments + RSS in Hugo PaperMod.
October 23, 2025 · 15 min · Iman Alipour Comments

> Short story: I wanted comments and a proper RSS feed on my Hugo + PaperMod site.
> Longer story: I spent 30 minutes poking around, and now you don’t have to. Here’s exactly what I did.

I’ve been wanting to add comment section to my blog for a while. There are a few problems.

- I don’t want to get attacked by bots or random people for no reason.
- I don’t want to allow weird things to happen.
- I don’t want to have a database for it.

So… I decided to take a path which is not necesserially the best. It requires a third party to act on your behalf, but it is not as scary as it sounds. According to Github:

> What the app can do The app’s rights are limited to the repo(s) where the site owner installed it and to the permissions it requested (basically: Discussions read/write + metadata). It can’t touch a commenter’s private repos or do things outside those scopes. GitHub’s docs also say a GitHub App can only do what both you and the app have permission to do.

> What “Act on your behalf” means That scary wording is GitHub’s. The giscus maintainer explains it means “post comments under your username,” and shows that the app requests Discussions read/write + metadata when installed.

> Do commenters have alternatives? Yes. Anyone can open the linked GitHub Discussion and comment directly on GitHub, bypassing the app’s OAuth popup. The README explicitly mentions this.

> Privacy & storage No tracking/ads; comments live in GitHub Discussions. giscus is open-source and has a published privacy policy. You can also revoke the app any time in your GitHub settings.

With the notice out of the way let’s dive right in!

## Why I chose Giscus (instead of Disqus)#

- No ads or trackers (my page weight thanks me).
- Uses GitHub Discussions (portable, transparent, easy to search).
- Readers log in with GitHub (no mystery auth popups).
- In theory you can directly go to the repo’s discussion section and comment there!

## What you need (for your site, not per user)#

- A Hugo site using PaperMod ✅
- A GitHub account ✅
- A public repository for the discussion threads (I called mine `blog-comments`) with Discussions enabled ✅
- Giscus app installed on that repo ✅

If you like to keep your main site repo clean, use a separate one, e.g. `github-username/blog-comments`.

## 1) Turn on comments with Giscus#

PaperMod renders a `comments.html` partial when `params.comments = true`.
So we enable it in config and create the partial.

### 1.1 Enable comments globally#

`hugo.toml` (snippet)

    [params]
      comments = true

You can still opt out per post with `comments = false` in front matter.

### 1.2 Create the comments partial#

Create this file in your site (not inside the theme):

layouts/partials/comments.html

Paste the Giscus embed (swap the placeholders with yours from giscus.app):

    <section id="comments" class="giscus">
      <script
        src="https://giscus.app/client.js"
        data-repo="yourname/blog-comments"
        data-repo-id="YOUR_REPO_ID"
        data-category="Comments"
        data-category-id="YOUR_CATEGORY_ID" <!-- Get them from Giscus's page! -->
        data-mapping="pathname"
        data-strict="0"
        data-reactions-enabled="1"
        data-emit-metadata="0"
        data-input-position="bottom"
        data-theme="preferred_color_scheme"
        data-lang="en"
        data-loading="lazy"
        crossorigin="anonymous"
        async>
      </script>
      <noscript>Enable JavaScript to view comments powered by Giscus.</noscript>
    </section>

Notes

- You’ll get `repo-id` and `category-id` from giscus.app after picking your repo + category.
- `data-mapping="pathname"` works great for static sites.
- Prefer a public repo so visitors can read discussions without friction.
- Want a different language? Change `data-lang` (e.g., `de`, `fr`).

## 2) Enable RSS (home + sections)#

Hugo already knows how to generate feeds; we just tell it where.

`hugo.toml`

    baseURL = "https://example.com/"  # set your production URL

    [outputs]
      home = ["HTML", "RSS", "JSON"]     # JSON is optional (e.g., for on-site search)
      section = ["HTML", "RSS"]
      taxonomy = ["HTML", "RSS"]
      term = ["HTML", "RSS"]

    [services.rss]
      limit = -1   # -1 = no cap; or set e.g. 20

Feed URLs

- Home feed: `/index.xml` → `https://example.com/index.xml`
- Section feeds: `/posts/index.xml`, `/notes/index.xml`, etc. (folders are lowercase)

> If you’re using a `.onion` address or staging domain, just set that in `baseURL`.
> Locally, Hugo serves feeds at `http://localhost:1313/index.xml`.

## 3) Show an RSS button on the home page#

PaperMod shows a nice RSS icon on section/taxonomy lists by default (when enabled), but not on the home page. Two options:

### Option A — Use the home “social icons” row#

This appears if you enable Home-Info or Profile mode:

    [params.homeInfoParams]
      Title = "Hello, internet!"
      Content = "Notes, experiments, and occasional rabbit holes."

    [[params.socialIcons]]
      name = "rss"        # lowercase matters
      url  = "/index.xml"

### Option B — Add an icon in the footer (theme-safe)#

Create:

layouts/partials/extend_footer.html

Paste:

    <a href="/index.xml" rel="alternate" type="application/rss+xml" title="RSS" class="rss-link">
      {{ partial "svg.html" (dict "name" "rss") }}
      <span>RSS</span>
    </a>

Make it a sensible size:

Create:

assets/css/extended/rss.css

Paste:

    /* Small & aligned RSS icon in the footer */
    .rss-link { display: inline-flex; align-items: center; gap: .35rem; }
    .rss-link svg { margin-left: 10px; width: 18px; height: 18px; } /* a bit of left margin for good measure!*/
    .rss-link span { font-size: .95rem; }

PaperMod auto-bundles anything under `assets/css/extended/`, so no extra imports needed.

## 4) Verify everything#

Build or run dev:

    hugo           # outputs to ./public
    # or
    hugo server    # serves at http://localhost:1313

Check feeds:

    # Home feed:
    curl -s http://localhost:1313/index.xml | head

    # A section feed (adjust path to your section name):
    curl -s http://localhost:1313/posts/index.xml | head

Check comments:

1. Open any post locally.
2. Scroll to the bottom — Giscus should appear.
3. Try a reaction or comment (you’ll be prompted to sign in with GitHub).

## 5) Per-post controls (handy later)#

Turn comments off for a single post:

    # in that post’s front matter
    comments = false

Full content in RSS (global):

    [params]
      ShowFullTextinRSS = true

Show RSS buttons on section/taxonomy lists:

    [params]
      ShowRssButtonInSectionTermList = true

## 6) Troubleshooting (aka “what I bumped into”)#

- Home page has no RSS icon
  That’s expected; either enable Home-Info/Profile mode + `socialIcons`, or use the footer partial.

- Section feed 404
  Folder names are lowercase (`content/posts/`, not `content/Posts/`).
  The URL mirrors that: `/posts/index.xml`.

- Giscus doesn’t create a discussion
  Double-check the four attributes: `data-repo`, `data-repo-id`, `data-category`, `data-category-id`.
  Make sure Discussions is enabled and the Giscus app is installed for the repo.

- Icon is comically large
  Keep the CSS above; 16–20px usually looks right.

## 7) Bonus: fast setup via GitHub CLI (optional, I didn’t use it, but I should’ve perhaps)#

    # Create the public comments repo (adjust names)
    gh repo create yourname/blog-comments --public -d "Blog comment threads" --confirm

    # Enable Discussions for it
    gh repo edit yourname/blog-comments --enable-discussions

Then visit giscus.app, select the repo + category (e.g. “Comments”), and copy the generated IDs into `layouts/partials/comments.html`.

### Final config snapshot (condensed)#

    baseURL = "https://example.com/"
    theme = "PaperMod"

    [outputs]
      home = ["HTML", "RSS", "JSON"]
      section = ["HTML", "RSS"]
      taxonomy = ["HTML", "RSS"]
      term = ["HTML", "RSS"]

    [services.rss]
      limit = -1

    [params]
      comments = true
      ShowRssButtonInSectionTermList = true
      ShowFullTextinRSS = true

    # Optional if using Home-Info/Profile mode:
    # [[params.socialIcons]]
    #   name = "rss"
    #   url  = "/index.xml"

# Appendix — Why I added Isso, how I wired it, and what I fixed#

## The story (why Isso + why I still keep Giscus)#

I wanted comments that:

- allow anonymous replies (no GitHub account required),
- are lightweight and self-hosted, and
- can work on my Tor `.onion` mirror.

Isso checks those boxes: it’s a tiny Python app with SQLite storage, no trackers, and a simple embed. At the same time, I like the developer-friendly workflow of Giscus (comments are GitHub Discussions), so I kept both and added a little switcher UI: “Anonymous (Isso)” or “GitHub (Giscus)”.

Result: readers can pick privacy/anon (Isso) or identity/notifications (Giscus).

## How I run it (high-level)#

- Site: Hugo + PaperMod
- Isso: listening on `127.0.0.1:8080`, stored locally (SQLite)
- Nginx: reverse-proxies `/isso/` to Isso on both the clearnet and the `.onion` vhost
- Hugo partial: renders the two panels (Isso & Giscus) and a switcher; Giscus is lazy-loaded and auto-rethemed with the site theme

> I’m deliberately keeping Isso’s own config tiny in this appendix; the important part for my setup is the Nginx proxying and the Hugo partial.

## Hugo partial: switcher + embeds#

Save as `layouts/partials/comments.html` and include it in your single layout (e.g. `layouts/_default/single.html`) with `{{ partial "comments.html" . }}`.

    <!-- comments.html -->
    <div class="comments-switch" style="display:flex;gap:.5rem;margin:.5rem 0 1rem;">
      <button id="btn-isso" type="button" aria-pressed="true">Anonymous (Isso)</button>
      <button id="btn-giscus" type="button" aria-pressed="false">GitHub (Giscus)</button>
      <a href="https://github.com/AlipourIm/blog-comments/discussions/categories/comments" target="_blank" rel="noopener">Open on GitHub ↗</a>
    </div>

    <!-- Isso panel (default) -->
    <div id="panel-isso">
      <section id="isso-thread"></section>
      <script
        src="/isso/js/embed.min.js"
        data-isso="/isso"
        data-isso-css="true"
        data-isso-lang="en"
        data-isso-max-comments-nested="5"
        data-isso-sorting="newest"
        async>
      </script>
      <small class="isso-powered" style="display:block;margin:.5rem 0;color:var(--secondary,#888)">
        Comments powered by <a href="https://isso-comments.de" target="_blank" rel="noopener">Isso</a>
      </small>
    </div>

    <!-- Giscus panel (lazy-loaded on click) -->
    <div id="panel-giscus" style="display:none">
      <section id="giscus-thread"></section>
    </div>

    <script>
    (function () {
      const panelIsso = document.getElementById('panel-isso');
      const panelGisc = document.getElementById('panel-giscus');
      const issoBtn = document.getElementById('btn-isso');
      const giscBtn = document.getElementById('btn-giscus');
      let gLoaded = false;

      function isDark() {
        // 1) explicit PaperMod preference
        const pref = localStorage.getItem('pref-theme');
        if (pref === 'dark')  return true;
        if (pref === 'light') return false;

        // 2) page state (classes / data-theme)
        const H = document.documentElement, B = document.body;
        const hasDark =
          H.classList.contains('dark') || B.classList.contains('dark') ||
          H.dataset.theme === 'dark'    || B.dataset.theme === 'dark' ||
          H.classList.contains('theme-dark') || B.classList.contains('theme-dark');
        if (hasDark) return true;

        // 3) OS preference
        return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
      }
      const gTheme = () => (isDark() ? 'dark_dimmed' : 'noborder_light');

      function loadGiscus() {
        if (gLoaded) return;
        const s = document.createElement('script');
        s.src = 'https://giscus.app/client.js';
        s.async = true;
        s.crossOrigin = 'anonymous';
        s.setAttribute('data-repo','AlipourIm/blog-comments');
        s.setAttribute('data-repo-id','R_kgDOQGARyA');
        s.setAttribute('data-category','Comments');
        s.setAttribute('data-category-id','DIC_kwDOQGARyM4Cw3x-');
        s.setAttribute('data-mapping','pathname');
        s.setAttribute('data-strict','0');
        s.setAttribute('data-reactions-enabled','1');
        s.setAttribute('data-emit-metadata','0');
        s.setAttribute('data-input-position','bottom');
        s.setAttribute('data-lang','en');
        s.setAttribute('data-theme', gTheme());  // initial theme
        document.getElementById('giscus-thread').appendChild(s);

        // Retheme once iframe exists
        const reTheme = () => {
          const iframe = document.querySelector('iframe.giscus-frame');
          if (!iframe) return;
          iframe.contentWindow?.postMessage(
            { giscus: { setConfig: { theme: gTheme() } } },
            'https://giscus.app'
          );
        };

        // PaperMod toggle button
        document.getElementById('theme-toggle')?.addEventListener('click', () =>
          setTimeout(reTheme, 0)
        );

        // Also react to attribute changes
        const mo = new MutationObserver(reTheme);
        mo.observe(document.documentElement, { attributes: true, attributeFilter: ['class','data-theme'] });
        mo.observe(document.body,             { attributes: true, attributeFilter: ['class','data-theme'] });

        gLoaded = true;
      }

      function show(which) {
        const showIsso = which === 'isso';
        panelIsso.style.display = showIsso ? 'block' : 'none';
        panelGisc.style.display = showIsso ? 'none'  : 'block';
        issoBtn?.setAttribute('aria-pressed', showIsso);
        giscBtn?.setAttribute('aria-pressed', !showIsso);
        if (!showIsso) loadGiscus();
      }

      issoBtn?.addEventListener('click', e => { e.preventDefault(); show('isso'); });
      giscBtn?.addEventListener('click', e => { e.preventDefault(); show('giscus'); });

      // default
      show('isso');
    })();
    </script>

## Nginx: proxy Isso on both sites (and avoid the 404-onion trap)#

The bug I hit: my `.onion` server had a regex static block that won over the plain `/isso/` location, so `/isso/js/embed.min.js` returned 404.

Fix: make `/isso/` a `^~` prefix location so it beats regex, and place it above the static block.

    # /etc/nginx/sites-enabled/onion-blog  (same idea for the clearnet vhost)
    server {
        listen 127.0.0.1:3301 default_server;
        server_name fjthpp2h3mj2rup25r3psmqamutnkbvxbpltlohdthw6fscgo3t6bpad.onion 127.0.0.1 localhost;

        add_header Referrer-Policy no-referrer always;
        add_header X-Content-Type-Options nosniff always;
        add_header X-Frame-Options SAMEORIGIN always;

        root /srv/hugo/mysite/public-onion;
        index index.html;

        location / { try_files $uri $uri/ /index.html; }

        # /isso -> /isso/
        location = /isso { return 301 /isso/; }

        # IMPORTANT: this must beat regex locations below
        location ^~ /isso/ {
            proxy_pass http://127.0.0.1:8080/;    # Isso container/port
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_read_timeout 60s;
        }

        # static
        location ~* \\.(css|js|ico|png|jpg|jpeg|gif|svg|webp|txt|xml)$ {
            access_log off;
            add_header Cache-Control "public, max-age=31536000, immutable";
            try_files $uri =404;
        }
    }

Reload and smoke test:

    sudo nginx -t && sudo systemctl reload nginx
    curl -I http://<your-onion-host>/isso/js/embed.min.js   # expect 200

> If you ever point `data-isso` to a different origin, add CORS headers on that vhost. For same-origin (`data-isso="/isso"`), you don’t need CORS.

## Small CSS tweaks (one color across light/dark + spacing)#

I wanted the same blue for reply / edit / delete links and for Submit / Preview buttons, in both themes, and a little spacing:

    /* put this in your site CSS */
    :root { --btn-blue: #2563eb; } /* adjust to taste */

    /* Isso form buttons */
    .isso-post-action input[type="submit"],
    .isso-post-action input[name="preview"] {
      background: var(--btn-blue) !important;
      color: #fff !important;
      border: none;
      padding: .5rem .75rem;
      border-radius: .4rem;
      cursor: pointer;
    }

    /* link actions under comments */
    .isso-comment-footer a {
      color: var(--btn-blue) !important;
      margin-right: .5rem;       /* gives "edit" and "delete" some breathing room */
      text-decoration: none;
    }
    .isso-comment-footer a:hover { text-decoration: underline; }

    /* keep name/email/website stacked, slightly larger */
    .isso-auth-section .isso-input-wrapper {
      display: block;
      margin: .35rem 0;
    }
    .isso-auth-section label { font-size: .95rem; }
    .isso-auth-section input[type="text"],
    .isso-auth-section input[type="email"],
    .isso-auth-section input[type="url"] {
      width: 100%;
      font-size: 1rem;
      padding: .5rem .6rem;
    }

## What changed (the fixes I actually made)#

1. Theme correctness for Giscus.
   PaperMod doesn’t add `.light`—it only toggles `.dark` and stores `pref-theme`. I now:

   - read `localStorage.pref-theme` first,
   - fall back to class/data-theme, then
   - fall back to OS preference.
     I also re-theme the Giscus iframe on every toggle via `postMessage`.

2. Isso over Tor.
   On the `.onion` vhost, I moved the proxy to a `^~ /isso/` block so it beats the static regex. That fixed the `404` on `/isso/js/embed.min.js`.

3. UI polish.

   - Unified button/link color across themes,
   - ensured “edit”/“delete” aren’t touching,
   - kept the author/email/website inputs stacked, and
   - left Submit/Preview styled and grouped.

## Sanity check#

- Toggle the theme: Giscus switches between `noborder_light` and `dark_dimmed` without reload.
- Open DevTools → Network on onion: `/isso/js/embed.min.js` loads with 200.
- Switcher buttons swap panels instantly; Giscus only loads when clicked.

## 8) Final notes!#

I could not fully fix the style of Isso. CSS is not easy… drat!

I don’t think anyone actually reads the blog, let alone comment on it. But it felt cool to have a comment section and also RSS for it. I had a lot of not so fun debugging experience, and will probably work on the styling to make it look right, but for now I’m happy with it! ^^

# Admin note — Delete all Isso comments for a single post#

This note is for future me: how to remove every comment tied to one post in Isso.
Tested with SQLite-backed Isso (default). Works whether you serve via clearnet or `.onion` — because this operates directly on the database.

## TL;DR (host with SQLite)#

> Replace the placeholders for `DB` and `POST_URI` first.

    # 0) Variables — edit these two lines for your setup
    DB="/var/lib/isso/comments.db"          # path to your Isso SQLite DB (check isso.conf: [general] dbpath)
    POST_URI="/posts/skin_routine/"         # the post's URI as stored by Isso (often just the path)

    # 1) Backup (always do this!)
    sqlite3 "$DB" ".backup '$(dirname "$DB")/comments.$(date +%F-%H%M%S).backup.sqlite3'"

    # 2) Inspect: find the thread row and preview the comments
    sqlite3 "$DB" "
    .headers on
    .mode column
    SELECT id, uri FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%';
    SELECT id, tid, created, author, text
    FROM comments
    WHERE tid IN (SELECT id FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%')
    ORDER BY created DESC
    LIMIT 25;
    "

    # 3) Delete all comments for that post (thread)
    sqlite3 "$DB" "
    DELETE FROM comments
    WHERE tid IN (SELECT id FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%');
    "

    # 4) (Optional) Remove the now-empty thread row too
    sqlite3 "$DB" "
    DELETE FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%';
    VACUUM;
    "

    # 5) Done. Isso usually picks this up automatically.
    #    If you're containerized and want to be safe:
    # docker restart <isso_container_name>

## If running Isso in Docker#

Open a shell in the container, then run the same steps:

    docker exec -it <isso_container_name> /bin/sh

    # Inside the container:
    DB="/db/comments.db"    # or /data/comments.db, check your image/volume mapping
    POST_URI="/posts/skin_routine/"

    sqlite3 "$DB" ".backup '/db/comments.$(date +%F-%H%M%S).backup.sqlite3'"
    sqlite3 "$DB" "SELECT id, uri FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%';"
    sqlite3 "$DB" "DELETE FROM comments WHERE tid IN (SELECT id FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%');"
    sqlite3 "$DB" "DELETE FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%'; VACUUM;"
    exit

    # Optionally restart the container:
    docker restart <isso_container_name>

## Notes & gotchas#

- Find the real DB path: In `isso.conf` (often `/etc/isso/isso.conf` or within your container at `/config/isso.conf`), look for:

      [general]
      dbpath = /var/lib/isso/comments.db

- What goes in `POST_URI`? Isso stores a `uri` string per thread. With the default embed config, it’s usually the path (`/posts/<slug>/`). If you’re unsure, list recent threads:

      sqlite3 "$DB" ".headers on" ".mode column" "SELECT id, uri FROM threads ORDER BY id DESC LIMIT 50;"

- Clearnet vs `.onion`: If you load the same post under multiple origins and your embed setup stores full origins, you may have multiple thread rows. The `LIKE` query above deliberately matches any uri containing your `POST_URI` to catch those.
- Rollback: To undo, stop Isso (optional), replace the DB with your backup (`comments.YYYY-MM-DD-HHMMSS.backup.sqlite3`), and start Isso again.
- HTTP API option: Isso supports `DELETE /<comment_id>` if admin endpoints/auth are enabled. For bulk removal it’s simpler and safer to use SQLite directly.
- Safety: Always run a backup first, and preview with the SELECT before you run the DELETE.

## One-liners for the impatient#

    DB="/var/lib/isso/comments.db"; POST_URI="/posts/skin_routine/"
    sqlite3 "$DB" ".backup '$(dirname "$DB")/comments.$(date +%F-%H%M%S).backup.sqlite3'"
    sqlite3 "$DB" "DELETE FROM comments WHERE tid IN (SELECT id FROM threads WHERE uri LIKE '%' || '$POST_URI' || '%');"
    sqlite3 "$DB" "DELETE FROM threads  WHERE uri LIKE '%' || '$POST_URI' || '%'; VACUUM;"

Isso container: quick checks & fixes for future me! (thank past me later ^^)

Find the container

    docker ps -a --format 'table {{.ID}}	{{.Names}}	{{.Status}}	{{.Ports}}' | grep -i isso

Inspect basic state

    docker inspect -f 'Name={{.Name}}  Running={{.State.Running}}  Status={{.State.Status}}  StartedAt={{.State.StartedAt}}  FinishedAt={{.State.FinishedAt}}' isso

Logs

    docker logs --tail=200 isso
    docker logs -f isso

Ports & reachability

    docker port isso
    sudo ss -ltnp | grep ':8080 '
    curl -i http://127.0.0.1:8080/

Restart policy (keep it running)

    docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' isso
    docker update --restart unless-stopped isso

Start/stop the container

    docker start isso
    docker stop isso

Who/what stopped it (events)

    docker events --since 24h --filter container=isso

Common config issue: duplicate options/sections If logs show DuplicateOptionError or DuplicateSectionError, fix `/config/isso.cfg` (remove duplicate `[server]` blocks or duplicate `public-endpoint`).

    nl -ba /config/isso.cfg | sed -n '1,120p'
    grep -n '^\[server\]' /config/isso.cfg
    grep -n '^public-endpoint' /config/isso.cfg

Using Docker Compose (run these in the directory with your compose file)

    docker compose ps
    docker compose logs --tail=200 isso
    docker compose up -d isso

If the container doesn’t exist (create/recreate)

    docker image ls | grep -i isso

    docker run -d   --name isso   -p 8080:8080   -v /srv/isso/config:/config   -v /srv/isso/db:/db   --restart unless-stopped   ghcr.io/posativ/isso:latest

Optional: exclude from auto-updaters (like Watchtower)

    docker update --label-add com.centurylinklabs.watchtower.enable=false isso

This note is intentionally self-contained so I can paste it at the end of the blog post as a maintainer-only appendix.

Downloads: Markdown · Signature (.asc)

View OpenPGP signature

    -----BEGIN PGP SIGNATURE-----

    iQIzBAABCgAdFiEEVaKl3oR5K6zGyu4/tYgoUOBMjSoFAmpkbuMACgkQtYgoUOBM
    jSr2VxAAgdHpf+4EIx2ASmSB+MeAHp7s1+2EPhmn96QuhiQO9Dr1e9250LbF/R8S
    A0zcN8mmyOtKv2rediU6HsGy6ddwdTAtpQDRvMw2Xuk2pBUZaG5LuvlNgSse9zVB
    dcG3GVLuMSRgNmyolhFoSWn46aa+3wZGrzYZQVUt8op+2fVp36agq2YoB4zeGKSm
    Ri43rO/kTingD0bclOA+SMbHpKQOcLyHwDlVrqIjVXcJ/kKLcm1G3Z5owo+gB6jY
    EMjxYiqyf5Zcbt4q/WzojbHLffjXoMzOgZ1sDOIObVQni9atgV49X4oIZ3+xSXSH
    W7ZbH6sg9LlrU8djddBXUKB0i72IVZ/4F5icVFUcK+szOmASy8fFP7gCOcCRATtb
    eNIFtiAlRXI0CqJdeq5fE9b+LX8lRpNnX229tg7GFgddzYUmFkKAsoJ9EUzUvUHm
    Xzqlm9DKy9LG/CeOxo473fIo4YCT2fcmMnt9nCZW4iDKOVl1nCupkTn5qsfNdpQM
    KycaNwsLBHPZWV+jDon8NEzYQk07n1Q9rlEWdL0egvn2S+pYnvLZbfi5dRhe+ciC
    qcEW/I1NZZRdU7MUEzhWvhbWsZtTkm6OevXjnqACv91DIQv7tNrKwZuASnpFeDRa
    GE0QYRrsaI3vCLR3cUmBAFsvZdwgzH0RQLb8w21XBW/BoFvixbA=
    =9k+S
    -----END PGP SIGNATURE-----

Verify locally:

    curl -fSLO https://blog.alipour.eu/sources/posts/new_features.md
    curl -fSLO https://blog.alipour.eu/sources/posts/new_features.md.asc
    gpg --verify new_features.md.asc new_features.md

Open on GitHub ↗
Comments powered by Isso
RSS · Visitors this week: —