fix(blog): resolve blog author avatars at build time#1879
fix(blog): resolve blog author avatars at build time#1879
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis pull request moves author avatar/profile resolution to build time and introduces distinct schemas for raw and resolved data. It adds ResolvedAuthorSchema and RawBlogPostSchema, updates blog loading to batch-fetch Bluesky avatars and enrich author objects, and preloads posts for generation. Several Vue components (AuthorList, BlogPostListCard, OgImage/BlogPost, BlogPostWrapper) change props to accept ResolvedAuthor[] and adjust usage to the resolved authors shape. Tests were updated to include avatar and profileUrl fields in test author fixtures. Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
modules/blog.ts (1)
88-91:⚠️ Potential issue | 🔴 CriticalGuard date normalisation to prevent build-breaking
RangeError.
new Date(...).toISOString()throwsRangeError: Invalid time valueon invalid dates, bypassing schema validation entirely and breaking the build. Invalid dates should fail validation gracefully instead of crashing the build process.Suggested fix
- if (frontmatter.date) { - const raw = frontmatter.date - frontmatter.date = new Date(raw instanceof Date ? raw : String(raw)).toISOString() - } + if (frontmatter.date) { + const parsedDate = frontmatter.date instanceof Date + ? frontmatter.date + : new Date(String(frontmatter.date)) + if (!Number.isNaN(parsedDate.getTime())) { + frontmatter.date = parsedDate.toISOString() + } + }
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/components/AuthorList.vueapp/components/BlogPostListCard.vueapp/components/OgImage/BlogPost.vueapp/components/global/BlogPostWrapper.vuemodules/blog.tsshared/schemas/blog.ts
| <div v-if="post?.authors" class="mb-12 max-w-prose mx-auto"> | ||
| <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> | ||
| <AuthorList :authors="frontmatter.authors" variant="expanded" /> | ||
| <AuthorList :authors="post.authors" variant="expanded" /> |
There was a problem hiding this comment.
Guard on author count, not just array existence.
post?.authors is truthy even when empty, so this section can render with no visible content.
Suggested fix
- <div v-if="post?.authors" class="mb-12 max-w-prose mx-auto">
+ <div v-if="post?.authors?.length" class="mb-12 max-w-prose mx-auto">📝 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.
| <div v-if="post?.authors" class="mb-12 max-w-prose mx-auto"> | |
| <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> | |
| <AuthorList :authors="frontmatter.authors" variant="expanded" /> | |
| <AuthorList :authors="post.authors" variant="expanded" /> | |
| <div v-if="post?.authors?.length" class="mb-12 max-w-prose mx-auto"> | |
| <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4"> | |
| <AuthorList :authors="post.authors" variant="expanded" /> |
| const response = await fetch( | ||
| `${BLUESKY_API}/xrpc/app.bsky.actor.getProfiles?${params.toString()}`, | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify fetch call currently lacks timeout/abort signal wiring
rg -nP "getProfiles\?" modules/blog.ts -C5
rg -nP "AbortController|signal:" modules/blog.ts -C3Repository: npmx-dev/npmx.dev
Length of output: 421
🏁 Script executed:
#!/bin/bash
# Get broader context around the fetch call to understand the function scope
sed -n '1,50p' modules/blog.tsRepository: npmx-dev/npmx.dev
Length of output: 1658
🏁 Script executed:
#!/bin/bash
# Get the rest of the function and where it's called
sed -n '45,100p' modules/blog.tsRepository: npmx-dev/npmx.dev
Length of output: 2038
🏁 Script executed:
#!/bin/bash
# Find where loadBlogPosts is called and if it's in module setup
sed -n '100,200p' modules/blog.tsRepository: npmx-dev/npmx.dev
Length of output: 2657
Add an abort timeout for the Bluesky fetch call.
A hanging Bluesky request can stall the full build because this runs during module setup (line 141 in the defineNuxtModule.setup() function).
Suggested fix
- const response = await fetch(
- `${BLUESKY_API}/xrpc/app.bsky.actor.getProfiles?${params.toString()}`,
- )
+ const controller = new AbortController()
+ const timeout = setTimeout(() => controller.abort(), 8000)
+ let response: Response
+ try {
+ response = await fetch(
+ `${BLUESKY_API}/xrpc/app.bsky.actor.getProfiles?${params.toString()}`,
+ { signal: controller.signal },
+ )
+ } finally {
+ clearTimeout(timeout)
+ }📝 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 response = await fetch( | |
| `${BLUESKY_API}/xrpc/app.bsky.actor.getProfiles?${params.toString()}`, | |
| ) | |
| const controller = new AbortController() | |
| const timeout = setTimeout(() => controller.abort(), 8000) | |
| let response: Response | |
| try { | |
| response = await fetch( | |
| `${BLUESKY_API}/xrpc/app.bsky.actor.getProfiles?${params.toString()}`, | |
| { signal: controller.signal }, | |
| ) | |
| } finally { | |
| clearTimeout(timeout) | |
| } |
🔗 Linked issue
🧭 Context
📚 Description
this is a slight perf improvement, hopefully!