程式碼背後:建構這個個人網站

起初,我只是想做一個網站來放我的履歷,覺得這樣會比較酷也比較方便。但隨著我陸續加入聊天機器人、首頁以及這個技術介紹頁面後,這個網站已經真正成為展現我個人能力的作品!最重要的是,我在這個過程中學到了非常多!

1. Astro SPA 中的狀態管理

右下角的互動小生物是我非常熱衷的一個小專案,我花了幾天的時間來完善眼球追蹤演算法和流暢的液體變形效果。然而,每當使用者點擊連結時,頁面就會重新整理,導致這些生物重置,破壞了原本的沉浸感。為了解決這個問題,我必須將這個網站轉換為單頁應用程式 (SPA)。

由於 Astro 本質上是一個多頁應用程式 (MPA) 框架,導入 Astro 的 <ViewTransitions /> 引發了一波生命週期 (lifecycle) 相關的 bug。我的客戶端 JavaScript 在新頁面上無法正常觸發,但同時我又需要讓這些小生物絕對不重新載入。我透過使用兩種不同的 Astro 指令來處理不同的元件邏輯,從而解決了這個問題。對於小生物,我使用了 persist 標籤,告訴 Astro 在頁面導覽之間無縫地保留該 HTML 節點。

Orange_Creature.astro
<div id="orange-creature" transition:persist>
</div>

對於標準的頁面互動(例如彈出視窗或懸停效果),腳本需要在使用者進入新路由時重新執行。因為標準的 DOMContentLoaded 在 Astro SPA 中沒有作用,所以我將邏輯包裝在 Astro 的自訂生命週期鉤子 (lifecycle hook) 中,以確保它在每次導覽時都會執行。

InteractiveCards.astro
// This ensures the logic re-runs every time a new page is injected into the DOM
document.addEventListener('astro:page-load', () => {
const interactiveCards = document.querySelectorAll('.interactive-card');
interactiveCards.forEach(card => initHoverLogic(card));
});

2. AI 聊天機器人:RAG 與系統提示詞工程

一開始,我以為建立 AI 後端會是最困難的部分。出乎意料的是,現代的 API 讓整合變得非常順利。真正的挑戰在於賦予機器人個性,並讓它基於我的真實資料進行回答。

我沒有選擇做一個普通的聊天機器人,而是運用了檢索增強生成 (RAG) 的原則以及嚴謹的系統提示詞工程。我設計了一個非常具體的系統提示詞,將我的履歷資料、專案經歷和嚴格的行為準則餵給 AI,確保它用我的語氣說話,並且只回答與我專業背景相關的問題。在前端部分,我將重心轉移到了 UI 和 UX 上。我打造了一個客製化的打字機效果來處理串流的文字區塊,並整合了來自 ZAPSPLAT 的精確音效,賦予聊天室一種實體機械鍵盤的觸感。

3. CI/CD、國際化 (i18n) 與 AI 結對編程

手動管理英文、日文和中文的翻譯簡直是一場架構上的噩夢。我需要將程式碼庫模組化,讓內容和程式碼完全解耦,但手動重構整個檔案樹可能要花上好幾天的時間。

為了解決這個問題,我轉向使用了本地的 AI CLI 代理工具。我寫下了嚴格的架構藍圖,並指示該代理工具直接在我的終端機中執行大規模、跨檔案的重構。由於讓 AI 擁有自主讀寫檔案系統的權限風險極高,我架設了一個安全的 Docker 容器來將 AI 「關」在裡面。這個沙盒確保了代理工具只能接觸到我的專案檔案,而這也成為了我學習基於 Docker 開發環境的契機。

4. 流暢動畫與使用者體驗 (UX)

現代的網頁應用程式需要具備良好的觸覺回饋感。我希望滾動頁面時能有滑行的感覺,並且元素能自然地顯現出來。我實作了 Lenis 來達成數學運算上的平滑滾動,並使用了 GSAP (GreenSock) 來處理複雜的滾動觸發動畫。因為我以前從未用過這些函式庫,這對我來說就像是一場速成班,我必須閱讀文件、管理時間軸狀態,並在 Astro 視圖轉換期間防止未掛載元件發生記憶體流失 (memory leaks)。

5. 跨越程式碼與畫布的橋樑

為了避免版權問題,我決定自己創作視覺素材。我曾短暫考慮過使用生成式 AI,但最後選擇了學習像素藝術 (Pixel Art)。我嚴重低估了它的難度!身為一個開發者,從純邏輯轉換到視覺 UI 設計,是我經歷過最陡峭的學習曲線。

我使用了 Aseprite 煞費苦心地逐格設計並製作像素藝術素材的動畫,這讓我學到了許多關於精靈圖 (sprite sheets) 和 CSS 關鍵影格 (keyframe) 整合的知識。整體而言,將我的技術背景轉化為視覺上具一致性的 UI——在 flexbox 限制、排版和留白之間取得平衡——是整個建置過程中最具挑戰性,但也最有成就感的一部分。



我的音效 (SFX) 是從哪裡來的?

我大部分的音效都是來自 ZAPSPLAT

特別感謝以下技術:

Astro LogoAstro.js
Google LogoGoogle Gemini & CLI
Docker LogoDocker
Docker LogoDocker
GitHub LogoGitHub
Aseprite LogoAseprite
Zapsplat LogoZAPSPLAT
GSAP LogoGSAP
Lenis