快轉到主要內容
Background Image

開張大吉|一些hugo施工筆記

·2982 字·6 分鐘
目錄

總的來說這次搭blog的體驗跟三年前相比真是好太多了,基本上沒有什麼感到stuck的時候。單獨開一篇施工筆記記錄一下我踩過的小坑,如果能幫助到別人就再好不過。

Theme
#

如您所見,本blog選了blowfish作為主題。感想是新手上路果然還是要選theme list上前幾名的,因為用的人多意味著可以到處抄代碼(不)。我上一個blog選的theme是Tufte,看中了它的side note section,當時腦中還瀰漫著一些陳腐的學生氣息,準備當成學習筆記來用,記一些tech notes/TIL什麼的,結果當然是半途而廢了。那個theme是從jekyll移植過來的,莫名奇妙有很多scss(好像和jekyll也沒有關係),搭的過程很令人頭痛,也沒有完整的open doc可以參考。換成blowfish以後整體過程流暢很多,有什麼問題基本都能在Official doc裡找到答案。

要特別注意的是params.toml 裡的colorScheme的value是小寫,小寫…不要像我一樣傻乎乎地複製下面example的標題。第一次deploy之後發現怎麼和本地相比色差那麼重,查了好久才發現是我把noir设置成了Noir

20250823003123_qanda.png
我煞有介事地問,GPT老師煞有介事地答

Firebase storage
#

上一個blog沒有考慮過存圖片的問題,所有照片統統丢给git repo。但是三年後的我當然不會這樣天真!我已經是一個立派會使用bucket的程序員了(叉腰)。 問了GPT老師firebase bucket和工作上打交道的GCS bucket到底有什麼區別,結果是除了權限控制(Storage Rules)的部分沒有區別, firebase本質就是GCS上的一個bucket。

小小的區別可能在於

  1. GCS的bucket要自己config,firebase直接分配一個現成的到手 → my-hugo-blog.appspot.com
  2. firebase的規則設置比較簡單(小型的Domain-Specific Language),不用管IAM,CRUD各自有各自的權限設定。
    firebase-rules

Uploading Script
#

既然是GCS上的🪣,就一定可以用gsutil 的CLI批量上傳。所以又請GPT老師幫我寫了一個script(不會自己寫bash也可以當engineer嗎ʕ •ᴥ•ʔ)

其實gsutil用的是Service Account認證, 所以可以繞開firebase的rules直接到達GCS bucket. Rules 只對「經過 Firebase API / SDK 的請求」生效。

20250823160255_auth-firebase-gcl.png
request flow
  • 記得先install gcloud-cli
brew install --cask gcloud-cli
  • log in一下
gcloud auth login
  • 然後在blog的根目錄新建一個upload.sh, 把這個script搬進去 不是根目錄也可以,重點是要注意這個script和要上傳的image的相對位置(relative path),要確保script可以找到要上傳的image。

    click me to expand
    #!/bin/bash
    # Usage:
    #   ./upload.sh file1.png file2.jpg
    #   ./upload.sh ./assets/img/20250816/*
    
    BUCKET="{your-project-id}.firebasestorage.app"
    
    # check the number of input arguments 
    if [ $# -eq 0 ]; then
      echo "❌ Please specify at least one file"
      exit 1
    fi
    
    # loop through the given diretory of image
    # upload one by one to firebase bucket
    for FILE_PATH in "$@"; do
      if [ ! -f "$FILE_PATH" ]; then
        echo "⚠️ File not found: $FILE_PATH"
        continue
      fi
    
      TIMESTAMP=$(date +%Y%m%d%H%M%S)
      FILE_NAME=$(basename "$FILE_PATH")
    
      NEW_FILE_NAME="${TIMESTAMP}_${FILE_NAME}"
      URL="https://firebasestorage.googleapis.com/v0/b/$BUCKET/o/$FILE_NAME?alt=media"
    
      echo "⬆️ Uploading $FILE_PATH to gs://$BUCKET/$NEW_FILE_NAME ..."
    
      # the line does the real job
      gsutil cp "$FILE_PATH" "gs://$BUCKET/$NEW_FILE_NAME" >/dev/null 
      URL="https://firebasestorage.googleapis.com/v0/b/$BUCKET/o/$NEW_FILE_NAME?alt=media"
      echo "📎 Image Url:"
      echo "$URL"
      echo
    done
    

  • 使用範例

# 工作路徑是根目錄, upload.sh 在根目錄,要上傳assets/blog-img/20250820/這個folder下的所有image
./upload.sh      assets/blog-img/20250820/* 
  • 如果upload.shassets在同一層級就會變成
# 工作路徑是根目錄 (要注意是在哪裡run這個script)
assets/upload.sh      blog-img/20250820/* 

Set up your blobcat reaction in twikoo
#

有關twikoo的設置過程已經有很多前輩寫過文章了!我就不再贅述。參考了以下兩篇前輩網友的blog↓

twikoo整體體驗是不錯,但是admin panel裡面會顯示評論的client以及IP還是令人有點不爽(雖然大概是為了防spam)在想要不要之後剝削claude code給我寫一個自用版本,把用不到的功能全部砍掉(畫餅)

owo.json config
#

從avocado老師那裡知道了slackmojis.com(雖然找到了blobcat大本營很開心但怎麼感覺在上班(不) 但誰能抵抗blobcat的誘惑呢!於是又剝削GPT老師幫我寫script。大致的思路↓

input a txt which contains all blobcats I want, parse the web and out put the owo.json.

  • 創建一個txt文件,列出想要抓取的blobcat name
// emojis.txt
cat_meow
catmoji_meow
fast_meow_party
meow_ace
python script.py  emojis.txt  

然後就可以獲得一個完全customized的owo.json了!

fetch your own blob cat
#

因為vercel實在是很好用於是又請claude搭了一個簡易UI.

方便不看代碼的朋友。(目前只能抓blobcat category因為我實在懶得和claude開會升級API了⋯⋯)

本來請佢升級了一個version,可以自定義抓取的category,但是因為升級後的UI實在太醜被我revert了:點擊看醜東西, 有力的朋友可以自己改改。

Deploy on Vercel
#

這次搭blog最大的升級是換deploy平台了!用上了Vercel,體驗真的是很好!

  • 可以一鍵import github repository, even with private repos (很適合工作私人github帳戶不分家的用戶比如我)
  • 完全不用操心CI/CD,所有的commit會直接同步到vercel上自動deploy,而且速度非常快
    • 不用再到處抄別人的github workflow yaml file了!
    • 可以直接選擇預先設置好的hugo framework, 不用自己填build/install/deploy command
  • 免費額度resource充足吃到飽
20250823154712_hugo-deploy.png
要手動設置的部分好像只有`HUGO_VERSION`

再見了Github Pages👋

Recap
#

距離第一次正經敲程式碼已經過去四年,開始幹工了之後其實很少再有那種自己在build something的興奮感。最初萌生建blog的想法也是因為想在換護照的最後一哩路上有事情可以做,不至於被等待的時間折磨。

快三十歲的我當然比十幾歲的我更厲害也更聰明,沒有理由再為準備逃離而虛擲光陰。這兩週每天下班之後泡在blog施工現場(當包工頭),收穫了久違的搭東西的快樂以及一個疼痛的肩膀,和兩個因為過度興奮而入睡失敗的晚上。感謝Claude Code和GPT老師,以及網友先輩,讓我這個沒有什麼審美的人也可以泳有一個還能看的過去的賽博小屋。

另外的感想是果然最快樂的瞬間還是用automation script實現本來很繁瑣的操作,比如上傳圖片獲取static url以及抓取blob cat的source url合成json配置文件 ——以前要花很久琢磨的生產力小工具現在只需要幾行prompt(和一顆願意和AI開會的心)就可以完成,快樂之餘不免有一些落寞 –build something is actually asking your AI agent to build something, debugging is no more than throwing whatever you got to Claude Code. 可以預見以後靠直覺debug靈光一現的時刻會越來越少,「build something from scratch」也會成為一個過時的短語吧。

模模糊糊記得一些本雅明在『機械複製時代的藝術作品』裡的論述,照相機的出現是如何打散傳統藝術傑作的Aura ——「複製」意味著「現在」與「此地」的無意義化,意味著「被複製物」的存在方式不再是獨一無二,AI之於code大概也是如此。但code畢竟和藝術作品不同,它本身就有極強的社區性和自帶的可複製性,它從來就不是不可接近,獨特性可能也僅僅落在個人的開發體驗上。不知道五年後(或是一年後)的光景是怎樣,但如果能看到有更多的女孩子能乘著AI的海浪成為工程師實在是樂事一樁,前現代的Aura要消失就消失吧,總會有新的Aura誕生的。