<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Hugo on Wayne X.Y. Blog</title>
    <link>/en/tags/hugo/</link>
    <description>Recent content in Hugo on Wayne X.Y. Blog</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Tue, 10 Mar 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="/en/tags/hugo/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Adding an Interactive Travel Map to Hugo Blog (Leaflet &#43; JSON)</title>
      <link>/en/2026/03/10/travel-map-leaflet-hugo/</link>
      <pubDate>Tue, 10 Mar 2026 00:00:00 +0000</pubDate>
      <guid>/en/2026/03/10/travel-map-leaflet-hugo/</guid>
      <description>&lt;h1 id=&#34;adding-an-interactive-travel-map-to-hugo-blog-leaflet--json&#34;&gt;Adding an Interactive Travel Map to Hugo Blog (Leaflet + JSON)&lt;/h1&gt;&#xA;&lt;p&gt;Recently, I wanted to add an interactive map to the top of my blog&amp;rsquo;s Travel page to mark the places I&amp;rsquo;ve visited. After some consideration, I decided to use the open-source and lightweight Leaflet.js, paired with a custom JSON file to manage the locations and marker colors.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;-implementation-goals&#34;&gt;🗺️ Implementation Goals&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Pin a map to the top of &lt;a href=&#34;/en/life/travel/&#34;&gt;&lt;code&gt;/life/travel&lt;/code&gt;&lt;/a&gt; to display the countries and places I&amp;rsquo;ve visited.&lt;/li&gt;&#xA;&lt;li&gt;Centrally manage location data (including English and Chinese names, latitude, longitude, and custom colors) via a JSON file.&lt;/li&gt;&#xA;&lt;li&gt;Use Leaflet.js to render the map, and automatically calculate the zoom boundaries (&lt;code&gt;fitBounds&lt;/code&gt;) based on the JSON data to perfectly fit all markers.&lt;/li&gt;&#xA;&lt;li&gt;Encapsulate the map into a Hugo Shortcode &lt;code&gt;&lt;link rel=&#34;stylesheet&#34; href=&#34;https://unpkg.com/leaflet@1.9.4/dist/leaflet.css&#34;&#xA;    integrity=&#34;sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=&#34; crossorigin=&#34;&#34; /&gt;&#xA;&lt;script src=&#34;https://unpkg.com/leaflet@1.9.4/dist/leaflet.js&#34;&#xA;    integrity=&#34;sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=&#34; crossorigin=&#34;&#34;&gt;&lt;/script&gt;&#xA;&#xA;&lt;div id=&#34;travel-map&#34; style=&#34;height: 400px; width: 100%; border-radius: 8px; margin-bottom: 2rem; z-index: 1;&#34;&gt;&lt;/div&gt;&#xA;&#xA;&lt;script&gt;&#xA;    document.addEventListener(&#34;DOMContentLoaded&#34;, function () {&#xA;        &#xA;        delete L.Icon.Default.prototype._getIconUrl;&#xA;        L.Icon.Default.mergeOptions({&#xA;            iconRetinaUrl: &#39;https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png&#39;,&#xA;            iconUrl: &#39;https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png&#39;,&#xA;            shadowUrl: &#39;https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png&#39;,&#xA;        });&#xA;&#xA;        var travelData = [{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:25.033,&#34;lng&#34;:121.5654,&#34;name_en&#34;:&#34;Taipei (Taiwan)&#34;,&#34;name_zh&#34;:&#34;台北 (台灣)&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.5902,&#34;lng&#34;:130.4017,&#34;name_en&#34;:&#34;Fukuoka City&#34;,&#34;name_zh&#34;:&#34;福岡市&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.2662,&#34;lng&#34;:131.3537,&#34;name_en&#34;:&#34;Yufuin&#34;,&#34;name_zh&#34;:&#34;由布院&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.2794,&#34;lng&#34;:131.5015,&#34;name_en&#34;:&#34;Beppu&#34;,&#34;name_zh&#34;:&#34;別府&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.173,&#34;lng&#34;:131.226,&#34;name_en&#34;:&#34;Kokonoe&#34;,&#34;name_zh&#34;:&#34;九重&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.0805,&#34;lng&#34;:131.1441,&#34;name_en&#34;:&#34;Kurokawa Onsen&#34;,&#34;name_zh&#34;:&#34;黑川溫泉&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:32.8062,&#34;lng&#34;:130.7058,&#34;name_en&#34;:&#34;Kumamoto&#34;,&#34;name_zh&#34;:&#34;熊本&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.1654,&#34;lng&#34;:130.4137,&#34;name_en&#34;:&#34;Yanagawa&#34;,&#34;name_zh&#34;:&#34;柳川&#34;},{&#34;color&#34;:&#34;red&#34;,&#34;lat&#34;:33.5215,&#34;lng&#34;:130.5348,&#34;name_en&#34;:&#34;Dazaifu&#34;,&#34;name_zh&#34;:&#34;太宰府&#34;}];&#xA;    var lang = &#34;en&#34;;&#xA;&#xA;    var map = L.map(&#39;travel-map&#39;, {&#xA;        scrollWheelZoom: true&#xA;    });&#xA;&#xA;    L.tileLayer(&#39;https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png&#39;, {&#xA;        attribution: &#39;&amp;copy; &lt;a href=&#34;https://www.openstreetmap.org/copyright&#34;&gt;OpenStreetMap&lt;/a&gt; contributors&#39;&#xA;    }).addTo(map);&#xA;&#xA;    var bounds = [];&#xA;&#xA;    if (travelData &amp;&amp; travelData.length &gt; 0) {&#xA;        travelData.forEach(function (loc) {&#xA;            var name = lang === &#34;en&#34; ? loc.name_en : loc.name_zh;&#xA;            var markerOptions = {};&#xA;            if (loc.color) {&#xA;                markerOptions.icon = new L.Icon({&#xA;                    iconUrl: &#39;https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-&#39; + loc.color + &#39;.png&#39;,&#xA;                    shadowUrl: &#39;https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png&#39;,&#xA;                    iconSize: [25, 41],&#xA;                    iconAnchor: [12, 41],&#xA;                    popupAnchor: [1, -34],&#xA;                    shadowSize: [41, 41]&#xA;                });&#xA;            }&#xA;            var marker = L.marker([loc.lat, loc.lng], markerOptions).addTo(map)&#xA;                .bindPopup(&#34;&lt;b&gt;&#34; + name + &#34;&lt;/b&gt;&#34;);&#xA;            bounds.push([loc.lat, loc.lng]);&#xA;        });&#xA;        map.fitBounds(bounds, { padding: [50, 50] });&#xA;    } else {&#xA;        map.setView([23.6978, 120.9605], 5); &#xA;    }&#xA;});&#xA;&lt;/script&gt;&lt;/code&gt; to easily reuse it across different language pages.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;-creating-the-data-file-data-layer&#34;&gt;💾 Creating the Data File (Data Layer)&lt;/h2&gt;&#xA;&lt;p&gt;First, create a &lt;code&gt;travel.json&lt;/code&gt; file under the &lt;code&gt;data/&lt;/code&gt; directory of your Hugo project. If you have new trips in the future, you just need to update this file without touching any code:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hugo Image Management: GitHub vs Cloudflare R2</title>
      <link>/en/2026/02/03/storing-asset/</link>
      <pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate>
      <guid>/en/2026/02/03/storing-asset/</guid>
      <description>&lt;h1 id=&#34;hugo-image-management-github-vs-cloudflare-r2&#34;&gt;Hugo Image Management: GitHub vs Cloudflare R2&lt;/h1&gt;&#xA;&lt;p&gt;&lt;a href=&#34;/en/2026/02/01/setup-hugo-blog/&#34;&gt;After setting up my Hugo blog&lt;/a&gt; and registering my own domain, I happily started updating the website via &lt;code&gt;git push&lt;/code&gt;. But looking at the repository contents, I felt that pushing images together seemed a bit off XD. As I continue updating and maintaining the blog, images will inevitably increase, taking up too much space. Plus, if I switch development environments, I&amp;rsquo;d have to re-download a bunch of images locally when pulling.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Build an Automated Personal Blog with Hugo &#43; Cloudflare Pages</title>
      <link>/en/2026/02/01/setup-hugo-blog/</link>
      <pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate>
      <guid>/en/2026/02/01/setup-hugo-blog/</guid>
      <description>&lt;h1 id=&#34;build-an-automated-personal-blog-with-hugo--cloudflare-pages&#34;&gt;Build an Automated Personal Blog with Hugo + Cloudflare Pages&lt;/h1&gt;&#xA;&lt;p&gt;Want to create a lightning-fast website that automatically updates every time you &lt;code&gt;git push&lt;/code&gt;? This article will guide you through building a personal blog using the &lt;strong&gt;Hugo&lt;/strong&gt; static site generator combined with &lt;strong&gt;Cloudflare Pages&lt;/strong&gt; automated deployment service.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;-why-this-combination&#34;&gt;🛠 Why This Combination?&lt;/h2&gt;&#xA;&lt;p&gt;Originally, I used GitHub Pages for hosting, but since the repository must be public, I decided to switch to Cloudflare Pages connected to my GitHub repo. The setup was simpler than expected, and after each &lt;code&gt;git push&lt;/code&gt;, GitHub Actions automatically runs and updates the website, ensuring everything works properly.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
