Lawtee News

How to Add an RSS Sidebar Widget to Hugo

Featured image of post How to Add an RSS Sidebar Widget to Hugo

This morning, I wanted to add an RSS widget to the sidebar of my Hugo homepage to display cross-site updates. It seemed simple enough, and I had even documented the main process on my 2025 page. However, as soon as I pushed the changes to GitHub, things went wrong. Both GitHub and Vercel failed to deploy the site. Here, I’ll document the subsequent steps in detail.

Adding an RSS Sidebar Widget to Hugo

In WordPress, adding an RSS plugin is straightforward with the default widgets, but in Hugo, it’s a bit more complicated. However, my goal was to output my latest WordPress posts to Hugo, which doesn’t necessarily require using RSS format. Instead, I could directly call the WordPress API. The method, though, is similar to using RSS.

  1. Add a Call Module to Hugo’s Sidebar Template

    • Method A: RSS Call

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      {{ $rssUrl := "https://news.lawtee.com/feed/" }} <!-- Replace with your RSS URL -->
      {{ $rss := resources.GetRemote $rssUrl }}
      {{ $items := $rss | transform.Unmarshal }}
      <h2>RSS</h2>
      <ul>
       {{ range first 7 $items.channel.item }}
       <li>
       <a href="{{ .link }}" target="_blank">{{ .title }}</a>
       </li>
       {{ end }}
      </ul>
      
    • Method B: WordPress API Call

      1
      2
      3
      4
      5
      6
      7
      8
      
      {{ $url := "https://news.lawtee.com/wp-json/wp/v2/posts?per_page=5" }} <!-- Replace with your WordPress URL -->
      {{ $posts := getJSON $url }}
      <h2>Latest Posts</h2>
      <ul>
       {{ range $posts }}
       <li><a href="{{ .link }}" target="_blank">{{ .title.rendered }}</a></li>
       {{ end }}
      </ul>
      
  2. Set Up Necessary CSS. For simplicity, I reused the CSS from another Hugo sidebar widget called archives.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    <section class="widget archives">
     <div class="widget-icon">
     {{ partial "helper/icon" "rss" }}
     </div>
     <h2 class="widget-title section-title">
     <a href="https://news.lawtee.com/" target="_blank">News</a>
     </h2>
     <div class="widget-archive--list">
     <ul>
     {{ range $posts }}
     <li><a href="{{ .link }}" target="_blank">{{ .title.rendered }}</a></li>
     {{ end }}
     </ul>
     </div>
     </section>
    

At this point, everything should have been fine, as I tested it locally using the Hugo Server command and everything worked perfectly. However, after pushing to GitHub, issues arose.

GitHub and Vercel Failed to Build the Remotely Called RSS Feed

  1. Error Situation. Both GitHub Actions and Vercel encountered the following error after npm run build:
1
ERROR render of "home" failed: "/home/runner/work/lawtee.github.io/lawtee.github.io/themes/hugo-theme-stack/layouts/index.html:18:7": execute of template failed: template: index.html:18:7: executing "right-sidebar" at <partial "sidebar/right.html" (dict "Context" . "Scope" "homepage")>: error calling partial: "/home/runner/work/lawtee.github.io/lawtee.github.io/themes/hugo-theme-stack/layouts/partials/sidebar/right.html:30:36": execute of template failed: template: partials/sidebar/right.html:30:36: executing "partials/sidebar/right.html" at <.link>: can't evaluate field link in type interface {}

In short, the template failed to render because it couldn’t read .link in the modified template. This .link should be the permalink of the article output by the RSS feed.

I double-checked the RSS feed format and found no issues. I began to suspect that GitHub might be unable to fetch the RSS file.

  1. Add Network Testing to the Workflow.
1
2
3
 - name: Test Network
 run: |
 curl -v "https://news.lawtee.com/feed/"

I added the above test to the deployment template in .github/workflow to see if GitHub could access the link. The result seemed fine.

  1. Troubleshooting the Issue.

It was strange. I spent the next hour debugging, including re-specifying the Hugo version, fixing some environmental discrepancies, modifying the template to pre-fetch the remote RSS file to the build server before Hugo builds, and switching between RSS and WordPress API. Despite all this, I only received a pile of deployment failure emails and made no progress.

  1. Confirming It’s a Network Issue.

Later, I carefully reviewed the network test results during the Actions deployment process. Around line 60, I noticed a 403 error. The reason was clear: during the build process, GitHub and Vercel’s server IPs were automatically blocked by Cloudflare as part of its defense mechanism against network attacks.

Adjust Cloudflare WAF Settings to Ensure GitHub and Vercel Servers Can Access the RSS Feed

Knowing the problem made it easier to solve. I added a custom WAF rule in Cloudflare to bypass the RSS feed URL.

However, this didn’t help. Upon closer inspection, I realized that WAF rules only apply to sporadic access, and Cloudflare’s automatic defense mechanism takes precedence over WAF rules. To adjust the priority of WAF custom rules, I needed to upgrade to a PRO account.

Fortunately, Cloudflare offers other configuration rules, such as “Page Rules,” which have higher priority than the firewall.

In the configuration rules, I set the security level of the links accessed during the build process to low, finally resolving the issue.

Note
If the RSS source site doesn’t use a firewall like Cloudflare, only the first step is needed to complete the setup.