traveling-around-the-world
一個以 React 為核心的單頁式應用程式(SPA),用來記錄自己走訪過的國家、城市與時間軸。初期資料儲存在瀏覽器 LocalStorage,並預留後端 Express + MongoDB 的擴充架構,後續可平滑升級成多人同步的雲端服務。
Monorepo 結構
traveling-around-the-world/
├─ client/ # Vite + React + TS 的前端 SPA
├─ server/ # Express + MongoDB (未來) API 服務
└─ shared/ # 前後端共用的型別定義
client
預設採 LocalStorage 擷取資料,並透過VisitProvider
可快速切換成 API 模式。server
已放好 Express + Mongoose 架構與 RESTful routes,只需接上 MongoDB 並啟動即可提供資料。shared
放行程型別VisitDto
,讓前後端保持相同資料契約。
前端(client)
技術與工具
- Vite + React 18 + TypeScript
- Material UI + Emotion 建構一致的 UI 與主題
- React Router 規劃 SPA 路由
- Zustand 追蹤 UI 狀態(訪問表單 Modal 與初始座標)
- React Query 統一處理資料讀寫與快取
- React Hook Form + Zod 表單驗證
- react-leaflet + OpenStreetMap 圖資,支援地圖點擊新增足跡
- i18next 支援中英文切換,分類與設定等字串同步集中管理
模組切分
features/map
:Leaflet 地圖、點擊事件、旅遊標記features/visits
:資料型別、LocalStorage Repository、React Query hooks、統計卡片與表單元件features/categories
:旅程分類 CRUD、React Query 與 sidebar 管理介面components/layout
:MUI AppBar + Drawer 布局、語言切換等元件state
:Zustand store 控制訪問建立/編輯的 Modalcomponents/overlay/VisitModal
:以 Modal 呈現足跡表單,必須先點擊地圖右下角的+
漂浮按鈕啟用定位,再第二次點擊地圖開啟表單components/overlay/NavControlsDialog
:App Bar 右上角的「更多」按鈕會開啟的快速操作 Modal(語言、分類切換、相關連結)
LocalStorage → API 的切換
- 預設
VisitProvider mode="local"
會載入localVisitRepository
。 - 改為
mode="api"
並設定apiBaseUrl
後,就會改用VisitApiClient
透過 REST API 存取。 - Vite
proxy
已轉發/api
至http://localhost:4000
,未來後端啟動後無需改動前端呼叫。
旅程分類管理
- 所有旅程可指定分類,未指定時會自動歸入「未分類」。
- 側邊欄可透過 chip 快速篩選「全部 / 未分類 / 自訂分類」。
- 在「管理分類」清單可新增、重新命名或刪除分類;刪除時相關旅程會回到「未分類」。
- 當前分類會記錄在 LocalStorage,在地圖右下角新增旅程時會自動帶入。
快速操作面板
- App Bar 右上角改為「更多」圖示,點擊後會開啟 Modal。
- Modal 集中展示語言切換、目前分類切換以及開發相關連結(OpenStreetMap、React Leaflet)。
- 便於未來擴充更多設定選項,而不把 App Bar 擠得太滿。
PWA 支援
- 新增 Web App Manifest(
client/public/manifest.webmanifest
)與 service worker 註冊,可在行動裝置安裝為獨立 App。 - 透過
vite-plugin-pwa
自動產生快取策略,支援離線瀏覽與版號自動更新。 - 內建
icons/icon-192.svg
、icons/icon-512.svg
,可於日後替換為專屬圖示。
多語系支援
- 透過
react-i18next
提供繁體中文與英文,語系檔位於client/src/locales/
。 - 右上角的語言選單 (
LanguageSwitcher
) 可即時切換語言,並記錄在 LocalStorage 方便下次載入。
開發啟動
- 安裝相依套件:
cd client && npm install
- 啟動開發伺服器:
npm run dev
- 瀏覽器開啟
http://localhost:5173
注意:Leaflet 需要載入 CSS(已在
TravelMap
中引入leaflet/dist/leaflet.css
)。
專案建置
- 推薦將
client/package.json
的build
指令改為"build": "tsc --noEmit && vite build"
,避免tsconfig.node.json
的noEmit
限制造成錯誤。 - 調整後可執行
npm run build
,產出靜態檔案於client/dist
。 - 首次啟用 PWA 時記得在
client
目錄重新執行npm install
,以安裝vite-plugin-pwa
相依套件。
部署到 Vercel
- 先在本地確認
npm run build
可成功(參考上節的建置指令變更)。 - 將整個專案推送至 GitHub / GitLab / Bitbucket。
- 在 Vercel 建立新專案時:
- Project Root:
client
- Build Command:
npm run build
- Output Directory:
dist
- Project Root:
- 連續部署:Vercel 會在每次 push default branch、自動建立 preview 的 PR 觸發建置並更新站台。
- 若後續要加上環境變數,可在 Vercel 專案設定內補上即可。
Docker Compose 啟動
若想直接以容器方式啟動整個堆疊(MongoDB + Node API + Nginx 前端):
- 建立映像:
docker compose build
- 啟動服務:
docker compose up -d
- 前端:http://localhost:3000
- API:http://localhost:4000
預設前端仍採 LocalStorage。如果要改用 API 資料來源,請在
client/src/app/App.tsx
把VisitProvider mode="local"
改成mode="api"
。
後端(server)
技術堆疊
- Express 4
- Mongoose 8 + MongoDB(內建 visit schema,資料結構與前端共用)
- Zod 驗證 API 請求 payload
- Helmet、CORS、Morgan 提供基礎安全與紀錄
架構亮點
src/app.ts
建立 Express App、共用中介層、/health
健康檢查src/modules/visits
:模型、Service、Controller、Router 切分清晰visit.mapper.ts
將 Mongoose Doc 轉成shared/visit.ts
的 DTOinfra/db/mongo.ts
佈建 Mongo 連線抽象
啟動指令
- 安裝套件:
cd server && npm install
- 建立
.env
(可複製.env.example
)並設定MONGODB_URI
- 開發模式:
npm run dev
- 編譯產出:
npm run build
->dist/
RESTful 端點:
GET /api/visits
:取得全部足跡POST /api/visits
:新增足跡GET /api/visits/:id
PUT /api/visits/:id
DELETE /api/visits/:id
共享型別(shared)
shared/visit.ts
定義 Visit DTO,前端Visit
及後端回傳皆採相同結構。- Vite 透過
@shared/*
alias 匯入,後端則直接使用相對路徑,確保型別同步。
開發流程建議
- LocalStorage MVP:僅啟動前端即可使用,點擊地圖開啟表單、資料存在瀏覽器。
- 串接 API:建立 MongoDB,啟動
npm run dev
後將前端VisitProvider
切換到 API 模式。 - Geocoding:前端已透過 Nominatim 反向地理編碼在點擊地圖時預填國家 / 城市;若需更高配額可在後端建立 Proxy。
- 照片/檔案:後端可擴增 S3/Cloudinary 上傳,再於前端
VisitCreateInput
增加檔案欄位。
待辦與下一步
- 實作 geocoding proxy,於點擊地圖後自動填入國家 / 城市
- 加入使用者認證(如 Auth0 或自建 JWT)以支援多人服務
- 將訪問紀錄導出成時間線或統計圖表(D3 / Recharts)
- 建立 Vitest / Jest 單元測試與 React Testing Library 元件測試
- 規劃 CI(GitHub Actions)自動執行
lint
與test
- 自動化部署流程模板(Vercel / GitHub Actions)
授權
本專案採用 MIT License,詳見 LICENSE
。
Languages
TypeScript
98.1%
Dockerfile
0.8%
HTML
0.7%
CSS
0.3%
JavaScript
0.1%