fix(enhancement): fixed the authorPage fallback by adding a precautiv…#319
fix(enhancement): fixed the authorPage fallback by adding a precautiv…#319devlopharsh wants to merge 5 commits intokeploy:mainfrom
Conversation
…e state and UX improvement Signed-off-by: developharsh <harsh237hk@gmail.com>
Signed-off-by: developharsh <harsh237hk@gmail.com>
|
@Achanandhi-M @amaan-bhati , Please have a review over the solution for the issue in the blog website , please let me know for further correction if needed , |
|
Hi @devlopharsh While reviewing the PR locally, the build fails during static page generation for the Could you please take a look at this and ensure the fallback logic properly handles cases where the author data might be undefined or missing during build time? Once the build passes successfully, we can proceed further with the PR. Thanks again for the effort! |
|
@dhananjay6561 okay sir , |
sure! |
Signed-off-by: developharsh <harsh237hk@gmail.com>
|
@dhananjay6561 , i have pushed the corrected code in my branch , the issue was becuase of minor variable accessing , corrected my code and pushed again !! |
|
Hey @devlopharsh 👋 — thanks for putting this PR together, we appreciate the effort! We've gone ahead and requested a Copilot review on this. Here's some context from the reviewer:
Once you've had a chance to go through the comments, please address the feedback and resolve the threads — and we'll get this across the line. Feel free to ask if anything's unclear. Happy coding! 💙 |
There was a problem hiding this comment.
Pull request overview
Improves the UX for author profile pages generated via getStaticPaths with fallback: true, preventing a misleading “No posts found” flash during ISR builds and providing a richer empty-state experience when an author truly has no posts.
Changes:
- Adds a fallback/loading UI wrapper (
AuthorEmptyState) with timed redirect for empty author pages. - Improves author name resolution (prefers
ppmaAuthorName, falls back to WordPressauthor.node.name). - Adjusts author-page data fetching to attempt matching via
getAllPosts()before other strategies.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
pages/authors/[slug].tsx |
Uses the new empty-state wrapper and updates author-name/metadata + matching logic in getStaticProps. |
components/postByAuthorMapping.tsx |
Adds a guard for empty filteredPosts and makes author name resolution more resilient. |
components/author-empty-state.tsx |
Introduces a client-side empty/loading wrapper with redirect countdown and image support. |
Comments suppressed due to low confidence (1)
pages/authors/[slug].tsx:39
- When
authorNameis unavailable (fallback render ornoPosts), the breadcrumb structured data usesname: "Author"and builds the URL with an empty slug (/authors/). That produces incorrect structured data for the actual/authors/[slug]page. Consider omitting the final crumb untilauthorNameis known, or using the requested slug for the crumb URL (and a stable display name) during fallback/empty states.
structuredData={[
getBreadcrumbListSchema([
{ name: "Home", url: SITE_URL },
{ name: "Authors", url: `${SITE_URL}/authors` },
{
name: authorName || "Author",
url: `${SITE_URL}/authors/${sanitizeAuthorSlug(authorName || "")}`,
},
]),
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const allEdges = allPostsResponse?.edges || []; | ||
|
|
||
| // 1) Try matching custom author field first (ppmaAuthorName) | ||
| filteredPosts = allEdges.filter(({ node }) => { | ||
| const candidateName = node?.ppmaAuthorName; | ||
| if (!candidateName || Array.isArray(candidateName)) { | ||
| return false; | ||
| } | ||
| return sanitizeAuthorSlug(candidateName) === sanitizeAuthorSlug(slugParam); | ||
| }); | ||
|
|
||
| // 2) If no match, try WordPress author name | ||
| if (!filteredPosts.length) { | ||
| try { | ||
| const allPostsResponse = await getAllPosts(); | ||
| filteredPosts = | ||
| allPostsResponse?.edges?.filter(({ node }) => { | ||
| const candidateName = node?.ppmaAuthorName; | ||
| if (!candidateName || Array.isArray(candidateName)) { | ||
| return false; | ||
| } | ||
| return sanitizeAuthorSlug(candidateName) === sanitizeAuthorSlug(slugParam); | ||
| }) || []; | ||
| } catch (error) { | ||
| console.error("authors/[slug] fallback to getAllPosts failed:", error); | ||
| filteredPosts = []; | ||
| filteredPosts = allEdges.filter(({ node }) => { | ||
| const authorName = node?.author?.node?.name; | ||
| if (!authorName || Array.isArray(authorName)) { | ||
| return false; | ||
| } | ||
| return sanitizeAuthorSlug(authorName) === sanitizeAuthorSlug(slugParam); | ||
| }); | ||
| } | ||
|
|
||
| // 3) If still no match and allPosts failed, fall back to direct author query | ||
| if (!filteredPosts.length && !allEdges.length) { | ||
| for (const candidate of Array.from(candidateAuthorNames)) { | ||
| if (!candidate) continue; | ||
| try { | ||
| const postsResponse = await getPostsByAuthorName(candidate); | ||
| const edges = postsResponse?.edges || []; | ||
| if (edges.length > 0) { | ||
| filteredPosts = edges; | ||
| break; | ||
| } | ||
| } catch (error) { | ||
| console.error( | ||
| `authors/[slug] failed to fetch posts for candidate "${candidate}":`, | ||
| error, | ||
| ); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The direct author lookup fallback only runs when allEdges is empty. Since getAllPosts() currently only returns the first page of posts (its GraphQL query doesn’t fetch pageInfo, so pagination stops after the first request), authors whose posts aren’t in that first batch will incorrectly render as noPosts. Consider running the getPostsByAuthorName candidate loop whenever there’s no match from allEdges (not only when allEdges.length === 0), or fixing getAllPosts() pagination and relying on it consistently.
| const noPosts = filteredPosts.length === 0; | ||
| const authorName = | ||
| filteredPosts?.[0]?.node?.ppmaAuthorName ?? | ||
| filteredPosts?.[0]?.node?.author?.node?.name; | ||
|
|
||
| return ( | ||
| <div className="bg-accent-1"> | ||
| <Layout | ||
| preview={preview} | ||
| featuredImage={HOME_OG_IMAGE_URL} | ||
| Title={`${authorName} Page`} | ||
| Description={`Posts by ${authorName}`} | ||
| Title={noPosts ? "Author Not Found" : `${authorName} Page`} | ||
| Description={ | ||
| noPosts ? "No posts found for this author" : `Posts by ${authorName}` | ||
| } |
There was a problem hiding this comment.
During fallback: true rendering, filteredPosts is still empty so noPosts becomes true and the page metadata is set to "Author Not Found" even though the UI shows a loading state via router.isFallback. This can flash an incorrect title/description to users and can be captured in previews. Consider checking router.isFallback in AuthorPage (via useRouter) and using a loading title/description (or deferring the "not found" metadata until after fallback resolves).
| } | ||
|
|
||
| return ( | ||
| <div className="w-full max-w-5xl mx-auto text-center md:text-left py-16 px-6 bg-white rounded-2xl shadow-sm border border-orange-100 flex flex-col md:flex-row md:justify-between items-center mb-15"> |
There was a problem hiding this comment.
mb-15 isn’t a default Tailwind spacing utility and there’s no custom 15 spacing configured in tailwind.config.js, so this margin class won’t apply. Use an existing spacing step (e.g. mb-14/mb-16) or an arbitrary value (e.g. mb-[60px]) if you need a specific size.
| <div className="w-full max-w-5xl mx-auto text-center md:text-left py-16 px-6 bg-white rounded-2xl shadow-sm border border-orange-100 flex flex-col md:flex-row md:justify-between items-center mb-15"> | |
| <div className="w-full max-w-5xl mx-auto text-center md:text-left py-16 px-6 bg-white rounded-2xl shadow-sm border border-orange-100 flex flex-col md:flex-row md:justify-between items-center mb-[60px]"> |
| if (imagePath.startsWith("/") && router.basePath) { | ||
| return `${router.basePath}${imagePath}`; | ||
| } | ||
| return imagePath; |
There was a problem hiding this comment.
imageSrc unconditionally prefixes router.basePath for any absolute path. In this codebase, public image paths are often already written with the /blog/... prefix (e.g. /blog/images/error404.png, /blog/images/author.png), so passing a pre-prefixed path would become /blog/blog/.... Consider guarding for imagePath.startsWith(router.basePath + '/') before prefixing, or standardizing the expected imagePath format for this component.
| if (imagePath.startsWith("/") && router.basePath) { | |
| return `${router.basePath}${imagePath}`; | |
| } | |
| return imagePath; | |
| if (!imagePath.startsWith("/") || !router.basePath) { | |
| return imagePath; | |
| } | |
| if ( | |
| imagePath === router.basePath || | |
| imagePath.startsWith(`${router.basePath}/`) | |
| ) { | |
| return imagePath; | |
| } | |
| return `${router.basePath}${imagePath}`; |
| <div className="w-full max-w-5xl mx-auto text-center md:text-left py-16 px-6 bg-white rounded-2xl shadow-sm border border-orange-100 flex flex-col md:flex-row md:justify-between items-center mb-15"> | ||
| <div> | ||
| <h1 className="text-3xl md:text-3xl font-bold text-orange-600 "> | ||
| OOPs!! No post found for the Author |
There was a problem hiding this comment.
Spelling/grammar in the empty-state heading: "OOPs!! No post found for the Author" should be corrected (e.g., "Oops! No posts found for this author").
| OOPs!! No post found for the Author | |
| Oops! No posts found for this author |
| </div> | ||
| </div> | ||
| <div> | ||
| <Image src={imageSrc} alt="errorImage" width={300} height={400} /> |
There was a problem hiding this comment.
The image alt text "errorImage" isn’t descriptive for screen readers. Use an alt text that describes the content/purpose (e.g. “404 illustration” / “No posts found illustration”), or empty alt ("") if it’s purely decorative.
| <Image src={imageSrc} alt="errorImage" width={300} height={400} /> | |
| <Image | |
| src={imageSrc} | |
| alt="No posts found for this author illustration" | |
| width={300} | |
| height={400} | |
| /> |
Related Tickets & Documents
Fixes: #3723
Description
Issue : When a new author slug was requested and getStaticPaths used fallback: true, the page rendered before data was ready and showed a false “No posts found” message.
Solution : I have fixed that by adding a fallback loading state and then improved the “no posts” UI/redirect flow. This would improve the UX of the website .
Changes
Type of Change
Testing and Demo
Screen.Recording.2026-02-05.011331.mp4
Screen.Recording.2026-02-06.000842.mp4
Checklist