Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 94 additions & 39 deletions app/api/og/post/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ import { db } from "@/lib/db/client"
import { posts } from "@/lib/db/schema"
import { getSiteOrigin } from "@/lib/utils"

async function fetchGitHubUser(username: string) {
const res = await fetch(`https://api.github.com/users/${username}`, {
headers: {
Accept: "application/vnd.github.v3+json",
...(process.env.GITHUB_TOKEN && {
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
}),
},
})
if (!res.ok) return null
const data = (await res.json()) as {
login: string
name: string | null
avatar_url: string
}
return { login: data.login, name: data.name || data.login, image: data.avatar_url }
}

const size = {
width: 1200,
height: 630,
Expand Down Expand Up @@ -48,6 +66,7 @@ export async function GET(request: NextRequest) {
title: posts.title,
number: posts.number,
rootCommentId: posts.rootCommentId,
authorId: posts.authorId,
Copy link
Contributor

Choose a reason for hiding this comment

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

Using internal database user ID instead of GitHub username in fetchGitHubUser() call causes API call to fail and wrong username displayed

View Details
📝 Patch Details
diff --git a/app/api/og/post/route.tsx b/app/api/og/post/route.tsx
index 1a8ba59..52025df 100644
--- a/app/api/og/post/route.tsx
+++ b/app/api/og/post/route.tsx
@@ -5,7 +5,7 @@ import type { NextRequest } from "next/server"
 import { join } from "path"
 import { getRootCommentText } from "@/lib/data/posts"
 import { db } from "@/lib/db/client"
-import { posts } from "@/lib/db/schema"
+import { posts, user } from "@/lib/db/schema"
 import { getSiteOrigin } from "@/lib/utils"
 
 async function fetchGitHubUser(username: string) {
@@ -67,8 +67,10 @@ export async function GET(request: NextRequest) {
         number: posts.number,
         rootCommentId: posts.rootCommentId,
         authorId: posts.authorId,
+        authorUsername: user.username,
       })
       .from(posts)
+      .leftJoin(user, eq(posts.authorId, user.id))
       .where(
         and(
           eq(posts.owner, owner),
@@ -82,7 +84,7 @@ export async function GET(request: NextRequest) {
     geistMonoBold,
   ])
 
-  const author = post?.authorId ? await fetchGitHubUser(post.authorId) : null
+  const author = post?.authorUsername ? await fetchGitHubUser(post.authorUsername) : null
 
   const title = post?.title || `Post #${postNumber}`
   const body = post?.rootCommentId
@@ -177,7 +179,7 @@ export async function GET(request: NextRequest) {
         >
           {author.image && (
             <img
-              alt={author.name || post.authorId}
+              alt={author.name || post.authorUsername}
               height={48}
               src={author.image}
               style={{ borderRadius: 24 }}
@@ -190,7 +192,7 @@ export async function GET(request: NextRequest) {
               color: "#71717a",
             }}
           >
-            {`@${post.authorId}`}
+            {`@${post.authorUsername}`}
           </span>
         </div>
       )}

Analysis

Bug Explanation

In app/api/og/post/route.tsx line 81, the code was passing post.authorId (an internal database user ID) to fetchGitHubUser(), which expects a GitHub username string.

The function fetchGitHubUser(username: string) calls https://api.github.com/users/${username}, which requires a valid GitHub username. However, post.authorId is the internal database user ID from the better-auth system (stored in the user table's id field).

Additionally, line 177 displays @${post.authorId} which shows the internal ID instead of the GitHub username, which is wrong for UI purposes.

This causes:

  1. GitHub API calls to fail with 404 because internal database IDs are not valid GitHub usernames
  2. The OG image to display internal database IDs instead of proper GitHub usernames

Fix Explanation

The fix involves three key changes:

  1. Import the user table: Added user to the imports from @/lib/db/schema to access user records.

  2. Join with user table: Modified the database query to perform a leftJoin with the user table on eq(posts.authorId, user.id) to retrieve the associated user record and its GitHub username.

  3. Select the username: Added authorUsername: user.username to the select clause to get the GitHub username from the joined user table.

  4. Use correct parameter: Changed fetchGitHubUser(post.authorId) to fetchGitHubUser(post.authorUsername) so the correct GitHub username is passed to the API.

  5. Update display: Changed the display from @${post.authorId} and alt text from post.authorId to use post.authorUsername instead, showing the GitHub username instead of the internal ID.

This ensures that:

  • The GitHub API call uses the correct GitHub username endpoint
  • The API call will succeed when the user has a GitHub username in their profile
  • The OG image displays the proper GitHub username to users

})
.from(posts)
.where(
Expand All @@ -63,6 +82,8 @@ export async function GET(request: NextRequest) {
geistMonoBold,
])

const author = post?.authorId ? await fetchGitHubUser(post.authorId) : null

const title = post?.title || `Post #${postNumber}`
const body = post?.rootCommentId
? await getRootCommentText(post.rootCommentId)
Expand All @@ -76,69 +97,103 @@ export async function GET(request: NextRequest) {
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
justifyContent: "flex-start",
justifyContent: "space-between",
backgroundColor: "#fafafa",
padding: 60,
gap: 32,
fontFamily: "Geist Mono",
}}
>
<div
style={{
display: "flex",
alignItems: "center",
gap: 12,
flexDirection: "column",
gap: 32,
}}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
alt="Forums"
height={40}
src={`${getSiteOrigin()}/icon.svg`}
width={40}
/>
<span
<div
style={{
fontSize: 36,
color: "#71717a",
display: "flex",
alignItems: "center",
gap: 12,
}}
>
{`${owner}/${repo}`}
</span>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
gap: 24,
}}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
alt="Forums"
height={40}
src={`${getSiteOrigin()}/icon.svg`}
width={40}
/>
<span
style={{
fontSize: 36,
color: "#71717a",
}}
>
{`${owner}/${repo}`}
</span>
</div>
<div
style={{
fontSize: 64,
fontWeight: 600,
color: "#09090b",
lineHeight: 1.2,
maxWidth: 1080,
display: "flex",
flexDirection: "column",
gap: 24,
}}
>
{title}
</div>
{body && (
<div
style={{
fontSize: 36,
color: "#52525b",
lineHeight: 1.5,
fontSize: 64,
fontWeight: 600,
color: "#09090b",
lineHeight: 1.2,
maxWidth: 1080,
display: "block",
lineClamp: 3,
}}
>
{body}
{title}
</div>
)}
{body && (
<div
style={{
fontSize: 36,
color: "#52525b",
lineHeight: 1.5,
maxWidth: 1080,
display: "block",
lineClamp: 2,
}}
>
{body}
</div>
)}
</div>
</div>
{author && (
<div
style={{
display: "flex",
alignItems: "center",
gap: 16,
}}
>
{author.image && (
<img
alt={author.name || post.authorId}
height={48}
src={author.image}
style={{ borderRadius: 24 }}
width={48}
/>
)}
<span
style={{
fontSize: 28,
color: "#71717a",
}}
>
{`@${post.authorId}`}
</span>
</div>
)}
</div>,
{
...size,
Expand Down