Skip to content

feat: add sponsorship page#52

Merged
mirumodapon merged 22 commits intomainfrom
add-sponsorship-page
Mar 29, 2026
Merged

feat: add sponsorship page#52
mirumodapon merged 22 commits intomainfrom
add-sponsorship-page

Conversation

@rileychh
Copy link
Copy Markdown
Member

@rileychh rileychh commented Mar 26, 2026

摘要

新增贊助方案頁面,資料來源為公開 Google Sheet,於 build time 透過 CSV export 取得。

主要變更

  • Schema:使用 Zod 定義贊助方案與加價購的 schema(shared/types/sponsorship.ts),通用 fetchSheet<K>() utility 提供型別推導
  • API routes/api/sponsorship/tiers/api/sponsorship/add-ons,欄位以 { zh, en } 結構回傳
  • 贊助方案:card layout,desktop 三欄、mobile 橫向滑動,各級別含 icon
  • 加價購:table layout,mobile 可橫向捲動,header 含 icon
  • 靜態內容:總覽、FAQ、關於 COSCUP 以 content/{zh,en}/sponsorship/ Markdown 檔管理,透過 ContentRenderer render
  • i18n:table label、級別名稱等短字串使用 component-scoped <i18n> block
  • Markdown render:使用 Nuxt Content 內建的 <MDC> component render Sheet 中的 Markdown 內容,無需額外套件
  • Layoutprose 由各頁面自行管理,不再放在 layout

注意事項

Important

內容沿用 2025 年版本,但非 1:1 複製——部分英文內容因排版需求有調整,請協助確認翻譯是否準確。

@rileychh-dokploy-coscup
Copy link
Copy Markdown

rileychh-dokploy-coscup bot commented Mar 26, 2026

Dokploy Preview Deployment

Name Status Preview Updated (UTC)
Nuxt ✅ Done Preview URL 2026-03-29T15:11:04.546Z

@rileychh rileychh marked this pull request as ready for review March 27, 2026 06:15
@rileychh rileychh requested a review from Copilot March 27, 2026 06:16
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 /sponsorship page 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()
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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().',
})
}

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +15
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
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
</nav>

<main class="mx-auto py-2 prose">
<main class="px-4 py-4">
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
<main class="px-4 py-4">
<main class="px-4 py-4 mx-auto max-w-4xl prose">

Copilot uses AI. Check for mistakes.
@mirumodapon mirumodapon force-pushed the add-sponsorship-page branch from ff30caf to df096eb Compare March 28, 2026 15:13
@mirumodapon mirumodapon force-pushed the add-sponsorship-page branch from df096eb to 7d63a3a Compare March 28, 2026 16:10
@mirumodapon mirumodapon merged commit 6794321 into main Mar 29, 2026
1 check passed
@mirumodapon mirumodapon deleted the add-sponsorship-page branch March 29, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants