fix: OG 메타태그 head 주입 - #152
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- RootLayout async 제거, SessionBridge로 분리하여 metadata streaming 문제 해결 - layout.tsx openGraph 이미지 URL 절대경로로 수정 - disputes/[id]/type/page.tsx OG fallback URL 절대경로로 수정 - JudgmentTypeResult 다운로드 버튼 anchor download 방식으로 통일 - kakaoShare.ts 미사용 파일 삭제 - invite/route.ts NEXT_PUBLIC_APP_URL → NEXT_PUBLIC_BASE_URL 교체 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRootLayout의 세션 전달이 Changes앱 세션·유형·다운로드·문구 조정
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@src/app/api/rooms/`[id]/invite/route.ts:
- Around line 81-82: The invite URL fallback in the room invite route currently
allows http://localhost:3030 in production when NEXT_PUBLIC_BASE_URL is missing,
which breaks the contract. Update the logic around inviteUrl generation in the
invite route so that localhost fallback is only used in development, and in
production it throws or fails fast when NEXT_PUBLIC_BASE_URL is unset. Use the
route handler and the appUrl/inviteUrl variables to locate the change, and keep
the returned invite link production-safe.
In `@src/app/layout.tsx`:
- Line 27: The Open Graph image URL in the metadata is hardcoded to a specific
deployment host, which can break previews, staging, and custom domains. Update
the metadata setup in the layout component to build the OG image URL from the
same base URL configuration used for invite links, using NEXT_PUBLIC_BASE_URL or
the shared base URL helper, so the og:image always resolves to an absolute URL
for the current environment.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 35225b7e-c739-4828-b858-504af93df4b1
📒 Files selected for processing (6)
src/app/(page)/disputes/[id]/type/page.tsxsrc/app/api/rooms/[id]/invite/route.tssrc/app/layout.tsxsrc/components/judgement/JudgmentTypeResult.tsxsrc/components/records/RecordListSection.tsxsrc/lib/utils/kakaoShare.ts
💤 Files with no reviewable changes (1)
- src/lib/utils/kakaoShare.ts
- invite/route.ts: NEXT_PUBLIC_BASE_URL 누락 시 프로덕션에서 CONFIG_ERROR 500 반환 - invite/route.ts: template literal → new URL()로 URL 조합 안전성 개선 - layout.tsx: OG 이미지 URL 하드코딩 제거, NEXT_PUBLIC_BASE_URL 기반으로 변경 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 `@src/app/api/rooms/`[id]/invite/route.ts:
- Around line 81-92: The invite flow in the route handler should validate the
service URL before any database work: move the appUrl check and inviteUrl
creation in the invite route’s main handler ahead of the transaction that
updates inviteTokenHash and INVITE_READY. Use the existing symbols appUrl,
inviteUrl, and the transaction block in the invite route so that CONFIG_ERROR or
invalid URL failures return early without persisting state.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 482385dc-1248-428e-9a92-a56b120b3cff
📒 Files selected for processing (2)
src/app/api/rooms/[id]/invite/route.tssrc/app/layout.tsx
| const appUrl = | ||
| process.env.NEXT_PUBLIC_BASE_URL ?? | ||
| (process.env.NODE_ENV === 'production' ? undefined : 'http://localhost:3030') | ||
|
|
||
| if (!appUrl) { | ||
| return NextResponse.json<ApiResponse>( | ||
| { success: false, error: { code: 'CONFIG_ERROR', message: '서비스 URL 설정이 누락되었습니다.' } }, | ||
| { status: 500 }, | ||
| ) | ||
| } | ||
|
|
||
| const inviteUrl = new URL(`/join/${token}`, appUrl).toString() |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
URL 설정 검증을 DB 트랜잭션보다 먼저 실행해주세요.
Line 85의 CONFIG_ERROR와 Line 92의 new URL() 검증이 Line 58-79의 트랜잭션 뒤에 있어, URL 누락/오입력 시 초대 토큰 해시와 INVITE_READY 상태가 저장된 뒤 실패 응답이 납니다. 설정 검증과 inviteUrl 생성을 먼저 끝낸 다음 DB를 갱신해주세요.
수정 예시
const token = generateInviteToken()
const tokenHash = hashInviteToken(token)
const expiresAt = getInviteExpiresAt()
+
+ const appUrl =
+ process.env.NEXT_PUBLIC_BASE_URL ??
+ (process.env.NODE_ENV === 'production' ? undefined : 'http://localhost:3030')
+
+ if (!appUrl) {
+ return NextResponse.json<ApiResponse>(
+ { success: false, error: { code: 'CONFIG_ERROR', message: '서비스 URL 설정이 누락되었습니다.' } },
+ { status: 500 },
+ )
+ }
+
+ let inviteUrl: string
+ try {
+ inviteUrl = new URL(`/join/${token}`, appUrl).toString()
+ } catch {
+ return NextResponse.json<ApiResponse>(
+ { success: false, error: { code: 'CONFIG_ERROR', message: '서비스 URL 설정이 올바르지 않습니다.' } },
+ { status: 500 },
+ )
+ }
await prisma.$transaction(async (tx) => {
await tx.disputeRoom.update({
where: { id },
@@
}
})
-
- const appUrl =
- process.env.NEXT_PUBLIC_BASE_URL ??
- (process.env.NODE_ENV === 'production' ? undefined : 'http://localhost:3030')
-
- if (!appUrl) {
- return NextResponse.json<ApiResponse>(
- { success: false, error: { code: 'CONFIG_ERROR', message: '서비스 URL 설정이 누락되었습니다.' } },
- { status: 500 },
- )
- }
-
- const inviteUrl = new URL(`/join/${token}`, appUrl).toString()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const appUrl = | |
| process.env.NEXT_PUBLIC_BASE_URL ?? | |
| (process.env.NODE_ENV === 'production' ? undefined : 'http://localhost:3030') | |
| if (!appUrl) { | |
| return NextResponse.json<ApiResponse>( | |
| { success: false, error: { code: 'CONFIG_ERROR', message: '서비스 URL 설정이 누락되었습니다.' } }, | |
| { status: 500 }, | |
| ) | |
| } | |
| const inviteUrl = new URL(`/join/${token}`, appUrl).toString() |
🤖 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 `@src/app/api/rooms/`[id]/invite/route.ts around lines 81 - 92, The invite flow
in the route handler should validate the service URL before any database work:
move the appUrl check and inviteUrl creation in the invite route’s main handler
ahead of the transaction that updates inviteTokenHash and INVITE_READY. Use the
existing symbols appUrl, inviteUrl, and the transaction block in the invite
route so that CONFIG_ERROR or invalid URL failures return early without
persisting state.
- layout.tsx, invite/route.ts, type/page.tsx 모두 NEXT_PUBLIC_APP_URL로 일관 적용 - type/page.tsx 하드코딩된 OG 이미지 URL 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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 `@src/app/`(page)/disputes/[id]/type/page.tsx:
- Around line 42-43: The metadata image URL fallback in the disputes page can
become a relative path in production when NEXT_PUBLIC_APP_URL is missing, which
breaks openGraph.images and twitter.images. Update the logic around the
appUrl/imageUrl setup in the page component so it never feeds relative image
URLs into metadata: either require a base URL and construct absolute URLs only,
or omit the image when a valid absolute base is unavailable, aligning this
page’s behavior with the metadataBase approach used in layout.tsx.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: a9b69847-2f4f-4f62-8747-83dab43eb2d8
📒 Files selected for processing (3)
src/app/(page)/disputes/[id]/type/page.tsxsrc/app/api/rooms/[id]/invite/route.tssrc/app/layout.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/layout.tsx
- layout.tsx: metadataBase 복원, NEXT_PUBLIC_APP_URL 적용, SessionBridge 분리로 metadata streaming 수정 - type/page.tsx: NEXT_PUBLIC_BASE_URL → NEXT_PUBLIC_APP_URL 통일 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev 복원 과정에서 participants 쿼리와 ownerName 반환값이 빠진 것 수정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/app/layout.tsx (1)
17-20: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
metadataBase의 base URL 환경변수를 invite/type 경로와 통일해주세요.이 PR에서
invite/route.ts와type/page.tsx는NEXT_PUBLIC_BASE_URL로 정렬되었는데, 여기metadataBase만NEXT_PUBLIC_APP_URL을 사용합니다. 배포 환경에서NEXT_PUBLIC_APP_URL이 설정되지 않으면VERCEL_URL/localhost:3030로 폴백되어 OG 이미지(상대 경로)가 잘못된 절대 URL로 해석될 수 있습니다. 동일 base URL 소스로 통일하는 편이 안전합니다.저장소 전반의 base URL 환경변수 사용을 확인합니다.
#!/bin/bash # NEXT_PUBLIC_APP_URL vs NEXT_PUBLIC_BASE_URL 사용처 비교 rg -nP 'NEXT_PUBLIC_(APP|BASE)_URL' --type=ts --type=tsx -C2 # .env 예시 파일에서 정의 여부 확인 fd -H -t f -e example -e env | xargs -r rg -n 'NEXT_PUBLIC_(APP|BASE)_URL' 2>/dev/null🤖 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 `@src/app/layout.tsx` around lines 17 - 20, `metadataBase` is using a different base URL source than the invite/type routes, so align it with `NEXT_PUBLIC_BASE_URL` in `layout.tsx`. Update the `metadataBase` URL construction to use the same environment variable fallback chain as `invite/route.ts` and `type/page.tsx`, removing the `NEXT_PUBLIC_APP_URL` dependency so OG image URLs resolve consistently across environments.src/app/(page)/disputes/[id]/type/page.tsx (1)
34-38: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win프로덕션에서
NEXT_PUBLIC_APP_URL미설정 시 OG/Twitter 이미지가 상대 URL이 됩니다.
baseUrl이''로 폴백되면imageUrl이/images/common/ogimg.jpg(상대 경로)가 되어openGraph.images/twitter.images에 그대로 들어갑니다.metadataBase가 설정돼 있지 않으면 절대 URL 요구사항을 만족하지 못해 미리보기가 깨집니다.metadataBase를 두고 상대 경로를 해석하게 하거나, 유효한 절대 base가 없을 때는 이미지를 생략하세요.🤖 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 `@src/app/`(page)/disputes/[id]/type/page.tsx around lines 34 - 38, The OG/Twitter image fallback in the metadata for the dispute type page can become a relative URL when NEXT_PUBLIC_APP_URL is missing, which breaks preview generation. Update the metadata setup in the page’s generateMetadata logic to either define metadataBase so openGraph.images and twitter.images can resolve relative paths correctly, or omit the image fields when a valid absolute base URL is unavailable. Make sure the fix is applied around the baseUrl and imageUrl construction in the page component.
🤖 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 `@src/app/`(page)/disputes/[id]/type/page.tsx:
- Around line 27-29: `getConflictType()` is returning a `ConflictTypePublicDto`
without the required `ownerName`, which breaks the API route contract and the
`ConflictTypeClient` fallback usage. Update
`src/app/(page)/disputes/[id]/type/page.tsx` in `getConflictType()` to include
`ownerName` from `dispute.aiJudgment.resultConflictDetail`, and ensure the
returned object matches `ConflictTypePublicDto` so
`src/app/api/disputes/[id]/conflict-type/route.ts` and `ConflictTypeClient.tsx`
can consume it consistently.
---
Duplicate comments:
In `@src/app/`(page)/disputes/[id]/type/page.tsx:
- Around line 34-38: The OG/Twitter image fallback in the metadata for the
dispute type page can become a relative URL when NEXT_PUBLIC_APP_URL is missing,
which breaks preview generation. Update the metadata setup in the page’s
generateMetadata logic to either define metadataBase so openGraph.images and
twitter.images can resolve relative paths correctly, or omit the image fields
when a valid absolute base URL is unavailable. Make sure the fix is applied
around the baseUrl and imageUrl construction in the page component.
In `@src/app/layout.tsx`:
- Around line 17-20: `metadataBase` is using a different base URL source than
the invite/type routes, so align it with `NEXT_PUBLIC_BASE_URL` in `layout.tsx`.
Update the `metadataBase` URL construction to use the same environment variable
fallback chain as `invite/route.ts` and `type/page.tsx`, removing the
`NEXT_PUBLIC_APP_URL` dependency so OG image URLs resolve consistently across
environments.
🪄 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: Repository UI (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 5ef78d69-972e-43a0-84de-dcf6d5dc22cb
📒 Files selected for processing (2)
src/app/(page)/disputes/[id]/type/page.tsxsrc/app/layout.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| return | ||
| } | ||
|
|
||
| const fileName = `갈등유형_${displayName}.jpg` |
There was a problem hiding this comment.
파일이름에 한글이 들어가지 않도록 설정 부탁드립니다
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
RootLayoutasync 제거 →SessionBridge서버 컴포넌트로 분리하여 metadata streaming 문제 해결layout.tsxmetadataBase복원,NEXT_PUBLIC_APP_URL기반 OG 태그 정상 주입disputes/[id]/type/page.tsxOG fallback URLNEXT_PUBLIC_APP_URL기반으로 수정,ownerName쿼리 추가JudgmentTypeResult다운로드 파일명 한글 제거 → 고정 영문(talkyowl-conflict-type.jpg)으로 변경JudgmentTypeResultanchor download 방식으로 통일kakaoShare.ts미사용 파일 삭제RecordListSection에러 메시지 마침표 제거Test plan
ogimg.jpg) 정상 노출 확인🤖 Generated with Claude Code