# 給前端／對方 AI：怎麼接這個後端

把這份整段貼給正在改「展覽日曆」前端的 AI。目標是把寫死在 HTML 的 `data-*` 改成打 API，**不要把 KLOOK／KKDAY 真實網址寫進前端**。

這個功能的後端前綴是 **`/api/exhibition`**。不要打舊的 `/api/exhibitions`、`/api/affiliate`、`/api/ingest`（已拿掉）。

## Base URL

兩條線，前端都用相對路徑打同一站的 `/api/exhibition` 即可：

| 線 | Base URL | 何時用 |
|--|----------|--------|
| 即時預覽 | `https://ai-dev.succ.work` | 看筆電現在跑的（Tunnel，關機就下線） |
| 公開 demo | `https://ai-dev-lab.a8092947.workers.dev` | 筆電可關；內容是上次 deploy |
| 本機直打 Worker | `http://127.0.0.1:8788` | 只測 API |

規格：同一站的 `/exhibition/openapi.yaml`（Tunnel 或 demo 都可以）。

整站探活（不屬展覽契約）：`GET /api/health` → `{ ok, features }`。

## 原則

1. 日期欄位用 `startDate`／`endDate`（`YYYY-MM-DD`）。畫面上的 `5/23 - 5/28` 用回傳的 `dateText`，或前端自己格式化。
2. 票券按鈕只帶 `offer.id`，開新分頁到：
   `{BASE}/api/exhibition/affiliate/redirect?offerId={offer.id}`
3. 不要 fetch 分潤轉向的 JSON；那是 `302` 導向。用 `window.open` 或 `<a target="_blank">`。
4. 錯誤格式固定：`{ "error": { "code": "NOT_FOUND", "message": "..." } }`
5. CORS 已開 `*`。若前端在別的 origin，直接打上述 Base URL。

## 對應原本 Demo 的畫面

| 原本前端 | 改成 |
|----------|------|
| `const exhibitions = [...]` 或卡片上的 `data-detail-*` | `GET /api/exhibition/exhibitions` |
| 週曆／月曆長條 | 用 `startDate`／`endDate` 算橫跨天數，不要再寫死 CSS 寬度 |
| 縣市篩選 | `?city=台北市` |
| 搜尋 | `?q=` |
| 詳情摘要／看點 | `GET /api/exhibition/exhibitions/{id}` 的 `summary`、`highlights` |
| `data-offer-id="offer-ceramic-klook"` | 來自 `offers[]`，不要依展名硬切 |
| Google Maps | `https://www.google.com/maps/search/?api=1&query={venue}`（這段仍可前端組，不必經後端） |
| 貼來源網址、自動整理 | `POST /api/exhibition/ingest/source` `{ "url": "..." }`。回傳只是擷取結果，**不會**自動變成展覽主檔 |

## 建議呼叫順序

首頁：

```
GET /api/exhibition/exhibitions?from=2026-05-18&to=2026-05-24
```

點卡片：

```
GET /api/exhibition/exhibitions/demo-ceramic-life
```

預訂：

```
GET /api/exhibition/affiliate/redirect?offerId=offer-ceramic-klook
```

目前 seed 裡的 offerId：

- `offer-ceramic-klook`
- `offer-ceramic-kkday`
- `offer-illustration-klook`
- `offer-photo-kkday`
- `offer-immersive-klook`
- `offer-ceramic-workshop-kkday`

## 先不要接

登入、收藏、Google Calendar OAuth、明信片審核、購票 webhook。那些 Demo 也只是模擬。等目錄與轉向穩定再做。

## 爬蟲邊界

`/api/exhibition/ingest/source` 只抓使用者貼上的公開 HTML（Open Graph／JSON-LD）。不要讓前端去爬 KLOOK 結帳頁；售票走 offerId 轉向。大量館方／文化部資料之後再換資料來源，**這組 endpoint 名稱可以不變**。
