<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blogging on Time Friend</title><link>https://time-friend.com/en/categories/blogging/</link><description>Recent content in Blogging on Time Friend</description><generator>Hugo</generator><language>en-GB</language><lastBuildDate>Wed, 29 Jul 2026 15:15:07 +0800</lastBuildDate><atom:link href="https://time-friend.com/en/categories/blogging/index.xml" rel="self" type="application/rss+xml"/><item><title>Adding an Animated Logo to My Blog</title><link>https://time-friend.com/en/archive/blog-architecture-animated-logo/</link><pubDate>Thu, 14 Aug 2025 17:00:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-animated-logo/</guid><description>&lt;p&gt;That small square in the top-left corner of the site? It&amp;rsquo;s a video.&lt;/p&gt;
&lt;p&gt;Grayscale by default. Lights up on hover — different color every time, and the playback speed surges then eases back down. Like it just woke up.&lt;/p&gt;
&lt;h1 id="why"&gt;Why&lt;/h1&gt;
&lt;p&gt;The old logo was a static PNG. It felt lifeless. I had a short video clip lying around, so I swapped the static image for a video.&lt;/p&gt;
&lt;h1 id="mp4-has-no-alpha-channel"&gt;mp4 Has No Alpha Channel&lt;/h1&gt;
&lt;p&gt;CapCut removed the background on export, but mp4 doesn&amp;rsquo;t support transparency — it gets baked to black.&lt;/p&gt;</description></item><item><title>How I Built the Homepage Typing Effect</title><link>https://time-friend.com/en/archive/blog-architecture-typing-effect/</link><pubDate>Tue, 12 Aug 2025 11:50:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-typing-effect/</guid><description>&lt;p&gt;When you open the homepage, you see text being typed out character by character. Not complicated, but many people ask how it&amp;rsquo;s done.&lt;/p&gt;
&lt;p&gt;This article explains the implementation.&lt;/p&gt;
&lt;h1 id="how-it-works"&gt;How It Works&lt;/h1&gt;
&lt;p&gt;When the homepage loads, it picks a random quote from a JSON file, and uses Typed.js to simulate typing.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Homepage loads
 ↓
main.js detects it&amp;#39;s the homepage
 ↓
Determine language (Chinese/English)
 ↓
Pick a random entry from /data/quotes.json
 ↓
Pass to Typed.js, start typing animation
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id="data-source-quotesjson"&gt;Data Source: quotes.json&lt;/h1&gt;
&lt;p&gt;Quotes are stored in &lt;code&gt;static/data/quotes.json&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Making My Blog Work Offline with PWA</title><link>https://time-friend.com/en/archive/blog-architecture-service-worker/</link><pubDate>Tue, 08 Jul 2025 15:30:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-service-worker/</guid><description>&lt;p&gt;PWA is a buzzword. For this blog, PWA means two things: manifest.json and Service Worker. manifest.json tells the browser &amp;ldquo;this is an app&amp;rdquo;, Service Worker makes it work offline.&lt;/p&gt;
&lt;p&gt;This article focuses on Service Worker since it&amp;rsquo;s the complex part. manifest.json is straightforward, covered at the end.&lt;/p&gt;
&lt;h1 id="what-is-service-worker"&gt;What is Service Worker&lt;/h1&gt;
&lt;p&gt;A Service Worker is a script that runs in the background of your browser. It&amp;rsquo;s independent of the web page, working silently behind the scenes.&lt;/p&gt;</description></item><item><title>Setting Up Page Analytics for My Blog</title><link>https://time-friend.com/en/archive/blog-architecture-analytics/</link><pubDate>Sun, 15 Jun 2025 13:20:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-analytics/</guid><description>&lt;p&gt;Writing a blog without knowing if anyone&amp;rsquo;s reading feels empty. Analytics isn&amp;rsquo;t for KPIs, just for fun.&lt;/p&gt;
&lt;p&gt;This blog has two analytics systems, each with its own purpose.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Busuanzi&lt;/strong&gt; shows on article pages, readers can see how many times each article has been viewed. Open source, no registration needed, just include a script.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Analytics&lt;/strong&gt; runs in the background, only I can see it. Used for traffic sources, user distribution, popular content, etc.&lt;/p&gt;</description></item><item><title>Adding a Comment System to My Blog</title><link>https://time-friend.com/en/archive/blog-architecture-giscus/</link><pubDate>Tue, 06 May 2025 10:30:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-giscus/</guid><description>&lt;p&gt;A blog needs comments. But I didn&amp;rsquo;t want to set up a database and moderation system just for that. Giscus is the compromise.&lt;/p&gt;
&lt;p&gt;This blog uses Giscus for comments. It&amp;rsquo;s based on GitHub Discussions. All comments live in the GitHub repo, no database needed, no third-party service.&lt;/p&gt;
&lt;h1 id="full-flow"&gt;Full Flow&lt;/h1&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;User opens article page
 ↓
Loads giscus.app/client.js
 ↓
Giscus script reads data- attributes
 ↓
Uses mapping=&amp;#34;pathname&amp;#34; to get current URL path
 ↓
Queries GitHub Discussions API for matching Discussion
 ↓
Found → renders comment box and existing comments
Not found → shows &amp;#34;leave a comment&amp;#34; input
 ↓
User writes comment → clicks submit
 ↓
Redirects to GitHub OAuth (first time only)
 ↓
Comment written to repo&amp;#39;s Discussions via API
 ↓
Giscus WebSocket listens for changes → real-time updates
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;User never leaves the page. Entire flow is seamless.&lt;/p&gt;</description></item><item><title>Deploying This Blog: From Push to Live</title><link>https://time-friend.com/en/archive/blog-architecture-deployment/</link><pubDate>Thu, 10 Apr 2025 15:44:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-deployment/</guid><description>&lt;p&gt;Static files need a place to live, accessible from anywhere in the world.&lt;/p&gt;
&lt;h1 id="platform-cloudflare-pages"&gt;Platform: Cloudflare Pages&lt;/h1&gt;
&lt;p&gt;Cloudflare Pages over other platforms, three reasons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Global CDN&lt;/strong&gt;: edge nodes worldwide, visitors load from nearest location&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero-config HTTPS&lt;/strong&gt;: automatic SSL certificate issuance and renewal&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Free tier&lt;/strong&gt;: enough bandwidth and build minutes for a personal blog&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Setup is simple: create a project in Cloudflare Pages dashboard, link your GitHub repo. Build commands and output directory are controlled in GitHub Actions, no need to configure in the dashboard.&lt;/p&gt;</description></item><item><title>What I Did for Google SEO on This Blog</title><link>https://time-friend.com/en/archive/blog-architecture-google-seo/</link><pubDate>Tue, 25 Mar 2025 11:08:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-google-seo/</guid><description>&lt;p&gt;This article only covers Google SEO. No other search engines. Reason: Google has the traffic share, doing Google well is enough.&lt;/p&gt;
&lt;h1 id="structured-data"&gt;Structured Data&lt;/h1&gt;
&lt;p&gt;The most important part. Structured data lets Google show rich results in search — publish date, author, summary.&lt;/p&gt;
&lt;p&gt;Every article gets JSON-LD injected at build time:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ if .IsPage }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;application/ld+json&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;@context&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;https://schema.org&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;@type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Article&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;headline&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ .Title }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;datePublished&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ .Date.Format &amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2006&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;T15&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Z07&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;dateModified&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ .Lastmod.Format &amp;#34;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2006&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;01&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;02&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;T15&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;04&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;05&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;Z07&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;00&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34; }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;author&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;@type&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;Person&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ .Site.Params.author }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ if .Description }}{{ .Description }}{{ else }}{{ .Summary | plainify }}{{ end }}&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ &lt;span style="color:#66d9ef"&gt;with&lt;/span&gt; .&lt;span style="color:#a6e22e"&gt;Params&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;tags&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ,&lt;span style="color:#e6db74"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;{{ delimit . &amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34; }}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {{ &lt;span style="color:#a6e22e"&gt;end&lt;/span&gt; }}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One thing to note: dates in JSON-LD must be ISO 8601 format (&lt;code&gt;2025-03-17T10:43:00+08:00&lt;/code&gt;). If you only provide date without timezone, Google might not parse it correctly. Hugo&amp;rsquo;s &lt;code&gt;.Date.Format&lt;/code&gt; outputs timezone by default, but if frontmatter doesn&amp;rsquo;t have timezone info, it assumes UTC — might not match your actual publish time.&lt;/p&gt;</description></item><item><title>How the Blog Build Pipeline Works</title><link>https://time-friend.com/en/archive/blog-architecture-build-pipeline-pwa/</link><pubDate>Wed, 05 Mar 2025 16:30:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-build-pipeline-pwa/</guid><description>&lt;p&gt;After writing articles, you don&amp;rsquo;t want to deploy them manually every time. The goal of automation is simple: push code and forget about it.&lt;/p&gt;
&lt;p&gt;Two things: turn Markdown into static files and put them on the internet. Plus, automate the whole build process.&lt;/p&gt;
&lt;h1 id="gulp-tasks"&gt;Gulp Tasks&lt;/h1&gt;
&lt;p&gt;Two Gulp tasks running in series:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;gulp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;task&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;default&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;gulp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;series&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;build&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;generate-service-worker&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="build"&gt;build&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;gulp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;task&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;build&amp;#39;&lt;/span&gt;, () =&amp;gt; &lt;span style="color:#a6e22e"&gt;gulp&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;./&amp;#39;&lt;/span&gt;).&lt;span style="color:#a6e22e"&gt;pipe&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;shell&lt;/span&gt;([&lt;span style="color:#e6db74"&gt;&amp;#39;hugo --buildFuture --minify&amp;#39;&lt;/span&gt;])));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One line. Runs Hugo build, &lt;code&gt;--buildFuture&lt;/code&gt; allows future-dated content, &lt;code&gt;--minify&lt;/code&gt; handles HTML/CSS/JS compression at build time.&lt;/p&gt;</description></item><item><title>Customizing My Blog Theme</title><link>https://time-friend.com/en/archive/blog-architecture-theme-customization/</link><pubDate>Sat, 15 Feb 2025 09:15:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-theme-customization/</guid><description>&lt;p&gt;The theme is &lt;code&gt;hugo-cactus-dark&lt;/code&gt;, a dark theme, clean and simple. Good enough for a blog.&lt;/p&gt;
&lt;p&gt;But the original theme only had basic features. I needed bilingual switching, Giscus comments, page analytics, structured data — none of these were included. So I forked it and overrode the templates I needed in &lt;code&gt;layouts/&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="what-was-overridden"&gt;What Was Overridden&lt;/h1&gt;
&lt;p&gt;Templates in &lt;code&gt;layouts/&lt;/code&gt; have higher priority than the same files in the theme. I only overrode what I needed to change.&lt;/p&gt;</description></item><item><title>Going Multilingual: i18n for My Blog</title><link>https://time-friend.com/en/archive/blog-architecture-i18n/</link><pubDate>Mon, 20 Jan 2025 14:21:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-i18n/</guid><description>&lt;p&gt;Writing a tech blog has an awkward problem: Chinese content serves domestic readers, but there&amp;rsquo;s also considerable overseas traffic. So I went with both languages.&lt;/p&gt;
&lt;p&gt;This blog is bilingual, Chinese and English. The same article has both versions, each with its own URL, independent of each other.&lt;/p&gt;
&lt;p&gt;i18n has two parts: &lt;strong&gt;content&lt;/strong&gt; internationalization (articles in both languages) and &lt;strong&gt;UI&lt;/strong&gt; internationalization (buttons, menus, text switches with language).&lt;/p&gt;
&lt;h1 id="content-internationalization"&gt;Content Internationalization&lt;/h1&gt;
&lt;h2 id="directory-structure"&gt;Directory Structure&lt;/h2&gt;
&lt;p&gt;Using Hugo&amp;rsquo;s &lt;code&gt;module.mounts&lt;/code&gt; for language mapping:&lt;/p&gt;</description></item><item><title>What My Blog Architecture Looks Like</title><link>https://time-friend.com/en/archive/blog-architecture-overview/</link><pubDate>Fri, 10 Jan 2025 10:00:00 +0000</pubDate><guid>https://time-friend.com/en/archive/blog-architecture-overview/</guid><description>&lt;p&gt;Many people are curious about how this blog is built.&lt;/p&gt;
&lt;p&gt;Looks simple, but there&amp;rsquo;s a lot behind it. Not a big project, but from an engineering perspective, I did quite a few things. Bilingual architecture, automated build pipeline, PWA, Google SEO, and so on.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;ll write a series to document the current setup. What I&amp;rsquo;m using, why I chose it, how the code is written, what performance considerations were made.&lt;/p&gt;</description></item><item><title>Automated Deployment of Hugo, Hexo Blog with Travis CI</title><link>https://time-friend.com/en/archive/automated-deployment-hugo-hexo-blog-with-travis-ci/</link><pubDate>Tue, 20 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/automated-deployment-hugo-hexo-blog-with-travis-ci/</guid><description>&lt;h1 id="what-is-travis-ci"&gt;What is Travis CI?&lt;/h1&gt;
&lt;p&gt;Travis CI is an online hosted CI service. Using Travis for continuous integration doesn&amp;rsquo;t require setting up your own server. Most importantly, it&amp;rsquo;s free for open source projects.
If company uses gitlab, it also provides corresponding continuous integration services. Won&amp;rsquo;t elaborate here.&lt;/p&gt;
&lt;h1 id="travis-ci-configuration-file"&gt;Travis CI Configuration File&lt;/h1&gt;
&lt;p&gt;Travis requires project root directory must have a &lt;code&gt;.travis.yml&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;When your repository has commits, travis will automatically execute the behaviors you configured below.&lt;/p&gt;</description></item><item><title>Make Your Hugo Blog Support ECharts Charts</title><link>https://time-friend.com/en/archive/make-your-hugo-blog-support-echarts-charts/</link><pubDate>Mon, 19 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/make-your-hugo-blog-support-echarts-charts/</guid><description>&lt;p&gt;In previously hexo built blog, had used charts, but now after migrating to hugo, there&amp;rsquo;s no related plugin support.&lt;/p&gt;
&lt;p&gt;So do it yourself, be self-sufficient.&lt;/p&gt;
&lt;p&gt;In hugo there&amp;rsquo;s a feature called &lt;code&gt;Shortcodes&lt;/code&gt;. Simply put it&amp;rsquo;s a small template that can pass parameters.&lt;/p&gt;
&lt;h1 id="create-shortcodes"&gt;Create Shortcodes&lt;/h1&gt;
&lt;p&gt;Create &lt;code&gt;./layouts/Shortcodes/echarts.html&lt;/code&gt; file&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;id&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;echarts{{ .Get `height` }}&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;width: 100%;height: {{.Get `height`}}px;margin: 0 auto&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;div&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;https://cdn.bootcss.com/echarts/3.8.0/echarts.common.min.js&amp;#34;&lt;/span&gt;&amp;gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;script&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;type&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;text/javascript&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Based on prepared dom, initialize echarts instance
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;myChart&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;echarts&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;init&lt;/span&gt;(document.&lt;span style="color:#a6e22e"&gt;getElementById&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;echarts{{ .Get `height` }}&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Specify chart configuration items and data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;option&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;({{ .&lt;span style="color:#a6e22e"&gt;Inner&lt;/span&gt; }})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Use just specified configuration items and data to display chart.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;myChart&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;setOption&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;option&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/&lt;span style="color:#f92672"&gt;script&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="usage"&gt;Usage&lt;/h1&gt;
&lt;p&gt;Insert echarts configuration data in Shortcodes, this way you can see a complete chart in the page&lt;/p&gt;</description></item><item><title>Hugo Blog Articles Not Displaying After Specified Time?</title><link>https://time-friend.com/en/archive/hugo-articles-not-displaying/</link><pubDate>Sun, 18 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/hugo-articles-not-displaying/</guid><description>&lt;p&gt;Since switching the blog to Hugo, encountered some pitfalls.&lt;/p&gt;
&lt;p&gt;Articles correctly added, page time adjusted to today, or after today, but cannot display in article list.&lt;/p&gt;
&lt;p&gt;The reason is that when Hugo templates loop through files, articles exceeding the current time won&amp;rsquo;t appear.&lt;/p&gt;
&lt;h2 id="timezone-issue"&gt;Timezone Issue&lt;/h2&gt;
&lt;p&gt;If your article time doesn&amp;rsquo;t specify a timezone.&lt;/p&gt;
&lt;p&gt;Like this &lt;code&gt;2018-11-19 16:14:25&lt;/code&gt;, the article likely won&amp;rsquo;t display.&lt;/p&gt;
&lt;p&gt;Hugo time is unified to Greenwich Mean Time, because China&amp;rsquo;s time is 8 hours earlier than Greenwich Mean Time.
When Greenwich Mean Time hasn&amp;rsquo;t reached your configured time, articles won&amp;rsquo;t appear in the article list.&lt;/p&gt;</description></item><item><title>Hugo Platform Articles Not Displaying After Specified Time?</title><link>https://time-friend.com/en/archive/hugo-articles-not-displaying-after-specified-time/</link><pubDate>Sun, 18 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/hugo-articles-not-displaying-after-specified-time/</guid><description>&lt;p&gt;Since blog switched to Hugo, encountered some pitfalls.&lt;/p&gt;
&lt;p&gt;Clearly correctly added articles, page time adjusted to today, or after today but cannot display in article list.&lt;/p&gt;
&lt;p&gt;Reason is Hugo template when looping through files, articles exceeding current time won&amp;rsquo;t appear.&lt;/p&gt;
&lt;h2 id="timezone-issue"&gt;Timezone Issue&lt;/h2&gt;
&lt;p&gt;If your article time doesn&amp;rsquo;t specify timezone.&lt;/p&gt;
&lt;p&gt;Like this &lt;code&gt;2018-11-19 16:14:25&lt;/code&gt;, article likely won&amp;rsquo;t display.&lt;/p&gt;
&lt;p&gt;Hugo time is unified to Greenwich Mean Time, because China&amp;rsquo;s time is 8 hours earlier than Greenwich Mean Time.
When Greenwich Mean Time hasn&amp;rsquo;t reached your configured time, articles won&amp;rsquo;t appear in article list.&lt;/p&gt;</description></item><item><title>Hugo Blog Baidu SEO Ultimate Optimization, Baidu Xiongzhang Auto Push</title><link>https://time-friend.com/en/archive/hugo-template-seo-optimization/</link><pubDate>Sat, 17 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/hugo-template-seo-optimization/</guid><description>&lt;p&gt;After switching to Hugo platform, the headache is that many SEO plugins from Hexo can&amp;rsquo;t be used.
Below I&amp;rsquo;ll share my SEO optimization solution.&lt;/p&gt;
&lt;h1 id="meta-tag-optimization"&gt;Meta Tag Optimization&lt;/h1&gt;
&lt;h2 id="description"&gt;Description&lt;/h2&gt;
&lt;p&gt;meta description, considered the most useful meta tag, is the website&amp;rsquo;s introduction information.
Content should be controlled within 100 characters.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;meta&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;description&amp;#39;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;itemprop&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;description&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ if .Description }}{{ .Description }}{{ else }}{{if .IsPage}}{{substr .Summary 0 100}}{{ end }}{{ end }}&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="keywords"&gt;Keywords&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ if .Keywords }} 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;meta&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ delimit .Keywords &amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}}&amp;#34;&lt;/span&gt; &amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{else}}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;meta&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;name&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;keywords&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;content&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;{{ delimit .Site.Params.Keywords &amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;,&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#960050;background-color:#1e0010"&gt;}}&amp;#34;&lt;/span&gt; &amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{{ end }}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="baidu-xiongzhang-push"&gt;Baidu Xiongzhang Push&lt;/h1&gt;
&lt;p&gt;Speaking of SEO, Xiongzhang is essential, it can achieve indexing within 24 hours. So this must not be missed.&lt;/p&gt;</description></item><item><title>Basic Usage of Hugo Blog Building Tool</title><link>https://time-friend.com/en/archive/basic-usage-of-hugo-blog-building-tool/</link><pubDate>Thu, 15 Nov 2018 16:14:25 +0000</pubDate><guid>https://time-friend.com/en/archive/basic-usage-of-hugo-blog-building-tool/</guid><description>&lt;p&gt;Finally migrated blog to &lt;code&gt;Hugo&lt;/code&gt;, initially most worried was this theme didn&amp;rsquo;t exist on &lt;code&gt;Hugo&lt;/code&gt; platform.
But got excited, spent two or three days. This theme. Completely migrated to &lt;code&gt;Hugo&lt;/code&gt; platform.
Next I&amp;rsquo;ll introduce &lt;code&gt;Hugo&lt;/code&gt; usage and pitfalls encountered, and solutions.&lt;/p&gt;
&lt;h1 id="hugo-performance"&gt;Hugo Performance&lt;/h1&gt;
&lt;p&gt;Precisely because hexo&amp;rsquo;s performance couldn&amp;rsquo;t satisfy, extremely unstable when generating static files. And time is relatively longer.
With same page count, processing speed hugo is 20 times or more than hexo. This is why I switched to Hugo.&lt;/p&gt;</description></item></channel></rss>