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.
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>
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
- Error Situation. Both GitHub Actions and Vercel encountered the following error after
npm run build
:
|
|
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.
- Add Network Testing to the Workflow.
|
|
I added the above test to the deployment template in .github/workflow
to see if GitHub could access the link. The result seemed fine.
- 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.
- 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.
Change Cloudflare WAF Settings to Ensure Github and Vercel Servers Can Access the RSS Address
Once the problem is identified, it can be resolved. Add a custom WAF rule in Cloudflare to bypass the RSS address.
However, this didn’t work. Upon closer inspection of Cloudflare, I realized that WAF rules only apply to scattered access, and Cloudflare’s automated defense system has higher priority than WAF rules. To adjust the priority of custom WAF rules, you must upgrade to a PRO plan.
Fortunately, Cloudflare has a variety of configuration rules that can be set, such as “Page Rules,” which have higher priority than the firewall.
So, I set the security level of the links accessed during the build process to “Disable” in the configuration rules.
Still, it didn’t work. I then discovered that Cloudflare’s Bot Fight Mode cannot be bypassed.
Either upgrade to a PRO plan or add IP rules. However, Github and Vercel use random Microsoft and Amazon IP addresses during deployment, making adding IP rules almost impractical.
The only solution left was to turn off Cloudflare’s Bot Fight Mode.
Note from Cloudflare Documentation
You cannot bypass or skip Bot Fight Mode using the Skip action in WAF custom rules or using Page Rules. Skip, Bypass, and Allow actions apply to rules or rulesets running on the Ruleset Engine. While Super Bot Fight Mode rules are implemented in the Ruleset Engine, Bot Fight Mode checks are not. This is why you can skip Super Bot Fight Mode, but not Bot Fight Mode. If you need to skip Bot Fight Mode, consider using Super Bot Fight Mode.
Bot Fight Mode can still trigger if you have IP Access rules, but it cannot trigger if an IP Access rule matches the request. For example, the IP Access rule matches the connecting IP.
Tip
If the RSS source site does not use a firewall like Cloudflare, only the first step is needed to complete the setup.