Conversation
There was a problem hiding this comment.
Pull request overview
Adds build-time, per-route Open Graph image generation for the Nuxt site (including session pages with agenda-specific cards), replacing the previous site-wide static og:image/twitter:image approach and ensuring images are produced during nuxt generate.
Changes:
- Integrates
nuxt-og-image(Takumi renderer) and adds OG templates (DefaultandSession) plus per-pagedefineOgImage(...)usage. - Extends prerendering to include bilingual session detail routes (
/session/:idand/en/session/:id) and relaxes Nitro prerender error handling. - Adds build/runtime dependencies and build script changes to support large-scale OG image generation (fonts, renderer deps, increased Node heap).
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks newly added OG-image, renderer, font, and build tooling dependencies. |
| package.json | Adds nuxt-og-image + renderer deps; increases build heap via cross-env in build script. |
| nuxt.config.ts | Registers modules, configures fonts for OG rendering, disables Nitro prerender fail-on-error, removes global static og/twitter image meta. |
| app/app.vue | Adds site-wide fallback defineOgImage('Default'). |
| app/pages/session.vue | Prerenders both zh (default) and /en session detail routes. |
| app/pages/session/[id].vue | Defines per-session OG images using the Session template with fetched session metadata. |
| app/pages/[...slug].vue | Defines per-content-page OG images using the Default template populated from content metadata. |
| app/components/OgImage/theme.ts | Introduces shared inline-style constants for OG image templates. |
| app/components/OgImage/Default.takumi.vue | Implements default OG card template layout for non-session pages. |
| app/components/OgImage/Session.takumi.vue | Implements session OG card template layout (title/speakers/room/time). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Dokploy Preview Deployment
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4003c3cb20
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
再麻煩幫我解一下衝突喔 |
Generate a branded OG image per route at build time with nuxt-og-image (Takumi renderer). Sessions render a card with title, speakers, room, and time; every other page uses a Default template. Session images are prerendered for both zh and en. - Add @nuxt/fonts with Noto Sans SC/TC/JP/KR (weight 400) for CJK glyph coverage. SC is primary: Takumi selects one font per script run rather than per glyph, and SC has the widest Han coverage (Simplified and Traditional, each in its correct form). - Add @iconify-json/noto for full emoji coverage (the module bundles only ~100 by default). - Raise the build heap to 8 GB via cross-env for 4 CJK fonts + ~670 images. - Set nitro.prerender.failOnError: false to tolerate transient Pretalx 500s. - Drop the static site-wide og:image/twitter:image meta; the module now injects both per page. - Share the colors, font-family chain, logo path, and base card layout across both templates via a small app/components/OgImage/theme.ts module.
Unbounded parallel prerendering spiked to ~12.6GB RSS during the session OG card render burst, OOM-killing the 16GB CI runner non-deterministically. Capping concurrency to 4 bounds the peak to ~10.2GB (independent of session count) while keeping build time flat.
|
我先處理沒辦法在本機上編譯,還有 |
- Disable Nuxt payload extraction: nuxt-og-image's isInternalRoute only skips
paths starting with "/_", so under baseURL "/2026" it processes the
"/2026/.../_payload.json" routes as real pages. defineOgImage on session
detail pages then made the renderer return no response (500) for those
payload routes during prerender.
- Drop the prerender failOnError override now that payload routes build
cleanly, restoring strict deploy-time error checking for the static build.
- Pass defineOgImage props via a variable: under the repo's strict
vueCompilerOptions, the inline object literal tripped TS2353 excess-property
checks because nuxt-og-image's ReactiveComponentProps resolves to {}.
📝 WalkthroughWalkthroughAdds OG image generation support by introducing shared theme constants and two new OG image components ( ChangesOG Image Generation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
Note 留言由 Claude 輔助撰寫。 已 rebase 並將 failOnError 改回嚴格模式(移除 failOnError: false),恢復靜態建置時的部署前錯誤把關。 先前之所以需要 修正方式是停用 Nuxt 的 payload extraction ( 參考: https://nuxt.com/docs/4.x/guide/going-further/experimental-features#payloadextraction |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dadf2c6337
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| width: '100%', | ||
| height: '100%', |
There was a problem hiding this comment.
Keep padded OG cards within the canvas
Both OG templates spread this base style and then add 72–80px of padding on the same root element. Because these templates use inline styles rather than a CSS reset/preflight, the root keeps the default content-box sizing, so width: '100%'/height: '100%' plus padding renders larger than the 1200x600 OG canvas and can clip the footer bar or session metadata at the bottom/right; add boxSizing: 'border-box' to the shared base style.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@nuxt.config.ts`:
- Around line 102-106: Remove the global experimental payloadExtraction override
in nuxt.config.ts so the site no longer disables payload splitting everywhere.
Update the Nuxt config around the experimental block to stop forcing
payloadExtraction false, and rely on nuxt-og-image 6.5.2’s baseURL-aware
behavior instead; keep the config change localized to the existing experimental
settings in the Nuxt configuration.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e3a078a6-eab8-40c6-9b8e-7bf187b8b971
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
app/app.vueapp/components/OgImage/Default.takumi.vueapp/components/OgImage/Session.takumi.vueapp/components/OgImage/theme.tsapp/pages/[...slug].vueapp/pages/session.vueapp/pages/session/[id].vuenuxt.config.tspackage.json
| experimental: { | ||
| // nuxt-og-image breaks payload-route rendering on pages that call defineOgImage | ||
| // under baseURL "/2026" (its isInternalRoute misses "/2026/.../_payload.json"), | ||
| // making the renderer return no response (500). Disable payload extraction. | ||
| payloadExtraction: false, |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does nuxt-og-image6.5.2 on Nuxt 4.4.x still requireexperimental.payloadExtraction = falsewhenapp.baseURLis a subpath like/2026, or is there a supported route-scoped workaround?
💡 Result:
As of nuxt-og-image version 6.5.2 running on Nuxt 4.4.x, setting experimental.payloadExtraction = false is no longer a documented or required workaround for handling app.baseURL subpaths. The module has received significant updates to its runtime configuration and path resolution logic [1][2][3], specifically improving support for custom baseURLs [4]. In modern versions of the module, the runtime configuration correctly consumes the app's baseURL [1], ensuring that OG image paths are generated with the correct base prefix automatically. If you are encountering issues with OG image path resolution or prerendering while using a subpath (e.g., /2026), ensure you are using the latest version of the module and that your site's baseURL is configured correctly in your nuxt.config.ts: export default defineNuxtConfig({ app: { baseURL: '/2026/', // Ensure trailing slash is included for consistency }, }) There is no supported route-scoped workaround for payload extraction because the issue you are referencing historically stemmed from how Nuxt itself handled base paths during static generation [5][6], which has been largely resolved in later Nuxt versions. If you face persistent 404s or path resolution errors, it is recommended to verify your environment configuration rather than disabling payload extraction, as disabling it may negatively impact performance and functionality [7].
Citations:
- 1: nuxt-modules/og-image@0a6f4084
- 2: nuxt-modules/og-image@56ad26a5
- 3: nuxt-modules/og-image@6c3b039b
- 4: chore(deps): update dependency nuxt-og-image to v4 nuxt/content#2896
- 5: Base URL doesn't get applied to /_payload.js when using Nuxi Generate nuxt/nuxt#15023
- 6: 'Cannot find any route matching' when using nuxi generate with custom app.baseURL nuxt/nuxt#20640
- 7: experimental.payloadExtraction warning fires unconditionally with ssr: false — schema overrides user config, then warning recommends impossible action nuxt/nuxt#34912
🏁 Script executed:
git ls-files nuxt.config.ts package.json pnpm-lock.yaml package-lock.json yarn.lock README.md docs 2>/dev/nullRepository: COSCUP/2026
Length of output: 202
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n## files\n'
git ls-files nuxt.config.ts package.json pnpm-lock.yaml package-lock.json yarn.lock README.md docs 2>/dev/null || true
printf '\n## search\n'
rg -n "nuxt-og-image|payloadExtraction|baseURL|app\.baseURL|site\.url|site\.name" nuxt.config.ts package.json README.md docs 2>/dev/null || trueRepository: COSCUP/2026
Length of output: 916
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,220p' nuxt.config.ts | cat -nRepository: COSCUP/2026
Length of output: 7430
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,140p' package.json | cat -nRepository: COSCUP/2026
Length of output: 2103
🌐 Web query:
nuxt-og-image 6.5.2 payloadExtraction baseURL subpath defineOgImage Nuxt 4.4.8
💡 Result:
In nuxt-og-image v6.5.2, configuration and behavior regarding base paths and payloads are handled through Nuxt's standard runtime configuration and internal module routing. Regarding the technical aspects mentioned: 1. payloadExtraction: While not explicitly defined as a top-level module option in documentation, nuxt-og-image relies on Nuxt's built-in payload extraction (used during build/prerendering). The module automatically handles the necessary context for generated images [1][2]. 2. baseURL and subpaths: When deploying a Nuxt application with a custom baseURL (e.g., set via app.baseURL in nuxt.config.ts), nuxt-og-image dynamically respects this configuration [1][3]. The module ensures that internal routes (such as the OG image generation endpoints, typically prefixed with /_og/) are correctly resolved relative to the defined base path [1][4]. If your application is hosted behind a reverse proxy, you must ensure the proxy correctly forwards the subpath to your Nuxt server to prevent 404 errors for these internal routes [5]. 3. defineOgImage: This composable remains the primary API for defining Open Graph images on a per-page basis [6][7]. In version 6.5.2, it has been refined to better support runtime configuration and path resolution [8][1]. You can use it as follows: defineOgImage({ component: 'MyComponent', props: { title: 'Hello' } }) For performance, if you are using an existing static image instead of generating one, use useSeoMeta instead to bypass the OG image generation logic: useSeoMeta({ ogImage: '/my-static-image.png' }) 4. Nuxt 4.4.8 Compatibility: nuxt-og-image v6.5.2 is designed to be compatible with modern Nuxt 4 releases. Ensure your environment matches the Nuxt 4 configurations for app.baseURL [3] and that no conflicting middleware is intercepting the /_og/ route path [4]. Top results: [1][3][7][4]
Citations:
- 1: nuxt-modules/og-image@0a6f4084
- 2: https://nuxtseo.com/docs/og-image/nitro-api/nitro-hooks
- 3: https://nuxt.com/docs/4.x/api/nuxt-config
- 4: https://github.com/harlan-zw/nuxt-og-image/blob/main/src/module.ts
- 5: https://www.answeroverflow.com/m/1463611921721851965
- 6: https://nuxtseo.com/docs/og-image/api/define-og-image
- 7: https://nuxtseo.com/docs/og-image/v5/api/define-og-image
- 8: nuxt-modules/og-image@v6.3.10...v6.5.2
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n "payloadExtraction|nuxt-og-image|defineOgImage|baseURL|/2026" README.md nuxt.config.ts pnpm-lock.yamlRepository: COSCUP/2026
Length of output: 1011
Remove the global payloadExtraction: false workaround. nuxt-og-image 6.5.2 already respects app.baseURL, so this disables payload splitting for the whole site unnecessarily.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@nuxt.config.ts` around lines 102 - 106, Remove the global experimental
payloadExtraction override in nuxt.config.ts so the site no longer disables
payload splitting everywhere. Update the Nuxt config around the experimental
block to stop forcing payloadExtraction false, and rely on nuxt-og-image 6.5.2’s
baseURL-aware behavior instead; keep the config change localized to the existing
experimental settings in the Nuxt configuration.
變更內容
Closes #127.
在建置階段為每個路由產生專屬的 Open Graph 預覽圖。
nuxt-og-image(Takumi renderer)在nuxt generate時輸出 PNG。字型與 CJK
@nuxt/fonts載入 Noto Sans SC / TC / JP / KR (皆 weight 400)。@iconify-json/noto完整支援 emoji(模組預設只內建約 100 個)。建置
cross-env將 heap 提高到 8 GB (4 套 CJK 字型 + 約 670 張圖片)。nitro.prerender.failOnError: false容忍 Pretalx API 偶發 500。og:image/twitter:image,改由模組逐頁注入。建置過程會出現
Could not resolve font "Segoe UI" for OG images.等找不到字體的錯誤,這是因為 UnoCSSpreset-wind4包含這些字體,但nuxt-og-image的isSystemFont()誤以為他們是外部字體而不是系統 fallback。這類警告可以安全的忽略。樣式為何止於 inline style + 常數 (無法再進一步重構)
兩個樣板共用的色彩、字型、Logo path 與基礎版面已抽到
app/components/OgImage/theme.ts,以 inline:style套用。Takumi renderer 的限制讓 CSS class 或共用 CSS 檔無法運作。實測結果::style+theme.ts常數bg-primary-800)<style src="./og.css"><script setup>中import './og.css'原因:
unocss-preset-theme以 CSS 變數(var(--primary-800))定義主題色,但靜態 renderer 取不到變數定義而卡住逾時;且 Takumi 只讀 inline:style、inline<style>文字與編譯後的 utility class,從不讀取外部或 JS 匯入的 CSS 檔。因此唯一同時「能共用又能正確渲染」的方式就是 JS/TS 常數。驗證
一些範例:
Summary by CodeRabbit
New Features
Bug Fixes