Conversation
Dokploy Preview Deployment
|
There was a problem hiding this comment.
Pull request overview
Adds a new Sponsorship page backed by data exported from a public Google Sheet (CSV) and localized static Markdown content, integrating it into the Nuxt 4 static-generation site.
Changes:
- Introduces Zod schemas + a typed
fetchSheet()utility to fetch/parse Google Sheets CSV and exposes sponsorship data via two new API routes. - Adds
/sponsorshippage UI (tiers cards + add-ons table) and new localized content files (overview/FAQ/about). - Adjusts layout styling responsibility (“prose”) from the default layout to individual pages; adds runtime config/env example for the sheet ID; updates dependencies.
Reviewed changes
Copilot reviewed 16 out of 24 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| shared/types/sponsorship.ts | Adds Zod schemas/types for tiers and add-ons. |
| server/utils/sheets/index.ts | Adds CSV fetch + parse utility for Google Sheets. |
| server/routes/api/sponsorship/tiers.get.ts | Adds tiers API route (returns { zh, en } fields). |
| server/routes/api/sponsorship/add-ons.get.ts | Adds add-ons API route (combines zh/en sheets). |
| app/pages/sponsorship.vue | Adds sponsorship page UI + i18n strings. |
| content/zh/sponsorship/{overview,faq,about}.md | Adds zh static content. |
| content/en/sponsorship/{overview,faq,about}.md | Adds en static content. |
| app/layouts/default.vue | Removes layout-level prose/centering; adds padding. |
| nuxt.config.ts | Adds runtimeConfig.googleSheetId. |
| .env.example | Documents NUXT_GOOGLE_SHEET_ID. |
| package.json / pnpm-lock.yaml | Adds csv-parse and zod dependencies. |
| pnpm-workspace.yaml | Enables saveExact: true workspace-wide. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export async function fetchSheet<K extends keyof typeof SHEETS>( | ||
| sheetName: K, | ||
| ): Promise<SheetResult<K>[]> { | ||
| const { googleSheetId } = useRuntimeConfig() |
There was a problem hiding this comment.
If googleSheetId is left as the default empty string, this builds an invalid Google Sheets URL and $fetch will fail with a hard-to-debug error. Consider validating googleSheetId and throwing a clear createError (including which runtime config/env var is missing) before making the request.
| const { googleSheetId } = useRuntimeConfig() | |
| const { googleSheetId } = useRuntimeConfig() | |
| if (!googleSheetId || typeof googleSheetId !== 'string' || googleSheetId.trim() === '') { | |
| throw createError({ | |
| statusCode: 500, | |
| statusMessage: | |
| 'Missing or empty "googleSheetId" in runtime config. Please set the environment variable or runtime config value used for the Google Sheets ID before calling fetchSheet().', | |
| }) | |
| } |
| import { TierLevelSchema } from '#shared/types/sponsorship' | ||
| import { useI18n } from 'vue-i18n' | ||
| import useLocaleContent from '~/composables/useLocaleContent' | ||
|
|
||
| const { t, locale, defaultLocale } = useI18n() | ||
|
|
||
| const { data: tiers } = await useFetch('/api/sponsorship/tiers') | ||
| const { data: addOns } = await useFetch('/api/sponsorship/add-ons') | ||
|
|
||
| const overview = await useLocaleContent('/sponsorship/overview', locale, defaultLocale) | ||
| const faq = await useLocaleContent('/sponsorship/faq', locale, defaultLocale) | ||
| const about = await useLocaleContent('/sponsorship/about', locale, defaultLocale) | ||
|
|
||
| const tierLevels = TierLevelSchema.options |
There was a problem hiding this comment.
TierLevelSchema (Zod) is imported into a page component just to get the enum values (TierLevelSchema.options). This pulls Zod into the client bundle, which is a noticeable size/perf hit for a static site. Consider exporting a plain const TIER_LEVELS = [...] as const from the shared module (and building the Zod enum from it) so the page can import the array without bundling Zod.
| </nav> | ||
|
|
||
| <main class="mx-auto py-2 prose"> | ||
| <main class="px-4 py-4"> |
There was a problem hiding this comment.
Removing mx-auto / prose from the default layout changes global typography/width for all pages using this layout. For example, the markdown catch-all page (app/pages/[...slug].vue) only adds prose and will no longer be centered (mx-auto) as before. Either keep the centering in the layout or ensure all affected pages add equivalent wrappers so this doesn’t regress existing content pages.
| <main class="px-4 py-4"> | |
| <main class="px-4 py-4 mx-auto max-w-4xl prose"> |
ff30caf to
df096eb
Compare
df096eb to
7d63a3a
Compare
摘要
新增贊助方案頁面,資料來源為公開 Google Sheet,於 build time 透過 CSV export 取得。
主要變更
shared/types/sponsorship.ts),通用fetchSheet<K>()utility 提供型別推導/api/sponsorship/tiers與/api/sponsorship/add-ons,欄位以{ zh, en }結構回傳content/{zh,en}/sponsorship/Markdown 檔管理,透過ContentRendererrender<i18n>block<MDC>component render Sheet 中的 Markdown 內容,無需額外套件prose由各頁面自行管理,不再放在 layout注意事項
Important
內容沿用 2025 年版本,但非 1:1 複製——部分英文內容因排版需求有調整,請協助確認翻譯是否準確。