前言

我製作了一個能將 MLB(美國職棒大聯盟)賽程自動同步到 Google 日曆・Apple 日曆的 Web 應用程式。
接下來會分享一些心得。

image.png

開發原因

最近我超級迷上大谷翔平所屬的道奇隊比賽!
不過,每天都要搜尋並確認比賽開始時間,或是大谷選手等先發出賽日,真的有點麻煩……

我想說「如果能自動同步到日曆就太方便了」,於是也找了現成的運動 App 和官方日曆,但還是有以下幾個不滿意的地方:

  • 幾乎不支援日曆連動
  • 就算能連動,也無法只篩選「大谷翔平或山本由伸的先發日」來加入

既然沒有現成的,那就自己做吧!因此我開發了這個能把比賽行程自動同步到平常使用的 Google 日曆與 iPhone 日曆的 Web 應用程式「SportsCal Sync」!

所製作應用程式的概要

可以做到的事

  • 道奇隊全賽程的比賽時間與轉播資訊同步到日曆
  • 只將大谷翔平・山本由伸・佐佐木朗希(道奇隊所屬日本投手)的先發預定篩選後同步到日曆
  • 支援 Google 日曆與 Apple 日曆(iPhone / Mac)
  • 只要註冊一次,之後賽程變動或新增都會自動反映到日曆(不用手動更新)

⚾ SportsCal Sync(應用程式在這裡)↓

使用方法

Step 1:選擇想同步的對象

  • 不能同時選擇多個,所以要針對每個想新增的對象,分別註冊一次

image.png

Step 2:在比賽預覽中確認內容

  • 會根據所選對象,顯示將加入日曆的比賽清單
  • 清單會自動捲動到「今天的比賽」附近,方便確認目前的註冊內容

image.png

Step 3:同步到日曆

  • 依照裝置選擇對應方式

image.png

同步到 Google 日曆時(Android / PC)

  • 會開啟彈出視窗
  • 依照畫面顯示的步驟開始同步

Google 日曆 App 在手機上不支援透過 URL 新增日曆,請在 PC 瀏覽器上操作。

image.png

新增到 iPhone / Mac 的日曆時

  • 會開啟彈出視窗
  • 依照畫面顯示的步驟開始同步

image.png

註冊後的日曆畫面

Google 日曆

  • 同步道奇隊比賽時
    スクリーンショット 2026-08-23 1.50.26.png

Apple 日曆

  • 同步道奇隊比賽時
    スクリーンショット 2026-08-23 2.28.03.png

各自只要註冊一次,之後即使不做任何事,日曆也會自動更新。即使比賽日程變更或新增,也會自動反映。


技術棧

image.png

領域技術用途前端React 19 + TypeScript + ViteSPA 建置UI 元件Chakra UI v3深色主題 UI後端Firebase Functions v2ICS 檔案動態生成代管Firebase HostingSPA 發佈 + ICS 路由外部 APIMLB Stats API比賽賽程・先發投手資訊(免費・免認證)CI/CDGitHub Actionsmain 合併後自動部署到正式環境、PR 預覽環境自動生成日曆「自動更新」的機制

這個應用程式的核心部分,所以我稍微說明一下 iCalendar 的運作方式。

iCalendar(.ics)是什麼

iCalendar(.ics 格式)是 RFC 5545 規範的日曆資料標準格式。Google Calendar、Apple Calendar、Outlook 等主要日曆 App 都支援。

當你在日曆 App 中註冊一個 URL 時,日曆 App 會定期前往該 URL 取得最新資料並持續自動更新。這不是伺服器主動推送,而是由日曆 App 端主動抓取的機制。

BEGIN:VCALENDAR
VERSION:2.0
REFRESH-INTERVAL;VALUE=DURATION:PT6H  ← 「請每 6 小時更新一次」的指示
X-WR-CALNAME:道奇隊 比賽賽程
X-APPLE-CALENDAR-COLOR:#005A9C

BEGIN:VEVENT
UID:[email protected]
DTSTART:20260407T021000Z
DTEND:20260407T051000Z
SUMMARY:道奇隊 vs 洋基隊
LOCATION:Dodger Stadium
DESCRIPTION:轉播:NHK-BS
END:VEVENT

END:VCALENDAR

REFRESH-INTERVAL;VALUE=DURATION:PT6H 是重點。這是 RFC 7986 定義的屬性,用來指示日曆 App「每 6 小時重新抓取一次這個 URL」。因此,使用者不需要做任何事,日曆就能持續更新。

透過 Firebase Hosting 的 rewrite 實現 ICS 端點

這個應用程式使用 firebase.json 的 URL rewrite 功能,將對 /ical/dodgers.ics 的存取轉送到 Firebase Functions(可在伺服器端執行處理的服務)。

{
  "hosting": {
    "rewrites": [
      { "source": "/ical/dodgers.ics", "function": "icalFeed" },
      { "source": "/ical/ohtani.ics", "function": "icalOhtaniFeed" },
      { "source": "/ical/yamamoto.ics", "function": "icalYamamotoFeed" },
      { "source": "/ical/sasaki.ics", "function": "icalSasakiFeed" }
    ]
  }
}

每當日曆 App 存取時,Functions 都會從 MLB API 取得最新資料並動態生成 ICS 回傳。這就是「自動更新」的真相。

遇到的困難與做的優化

第一次實作 iCalendar

這次是我第一次處理 iCalendar(.ics),所以在規格與實作方式的調查上花了不少功夫。

並不是只要單純生成 .ics 檔案就好,還需要理解透過 URL「訂閱」日曆的機制、Google Calendar / Apple Calendar 的註冊差異,以及更新會在什麼時機反映等,很多事情都是實際查過才知道的。

我也學到,對於第一次接觸的技術,先理解機制,再整理出「這次需求到底需要做到什麼程度」後再實作,是非常重要的!

聚焦 MVP(最小可行產品)所需功能

這次為了最快把價值交付出去,我非常重視 MVP 架構。現階段判斷不需要使用者登入功能或資料庫管理,因此徹底刪減功能。結果在降低維護成本的同時,也能用簡潔的架構完成發布!

事前設計與實作時的彈性轉向

在開始實作前,我先把 UI 設計、使用情境定義、Domain 設計、API 設計、目錄結構等內容都完整規劃好,再開始開發。
但實際動手之後,常常會發現「比起這個設計,換成另一種架構或資料流,能讓使用者體驗(UX)或維護性更好」。我沒有過度堅持初期設計,而是根據實作時的發現,持續彈性重構,這也是很好的學習經驗!

結語

現在 AI 雖然正在發展,也能提升開發效率,
但我認為,「要選哪種技術」「要做什麼設計」「AI 提出的實作真的適合嗎」 的判斷能力,比以往更加重要。

未來我也會持續累積知識與經驗,讓自己能在理解技術與設計的基礎上,依照情境做出正確判斷!另外,這次在 iCalendar、Firebase,以及設計與技術選型上學到的內容,也會活用在之後的開發中!

參考

  • Chakra UI 官方文件

  • Cloud Functions 官方文件

  • 其他參考文章

JISOU 成員募集中!

程式設計教練 JISOU 正在招募新成員。
要不要加入日本第一的輸出型社群,一起提升職涯呢?
有興趣的人,請務必來看看首頁!
▼▼▼


原文出處:https://qiita.com/takahiro_honda/items/b44d4e2b526aa009f822


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝15   💬4  
199
🥈
我愛JS
💬1  
6
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登