Deduplicate getPost calls in post page (generateMetadata + prefetch)
Problem
Post pages (/@author/permlink, /hive-123/@author/permlink) call getPost() twice during SSR - once in generateMetadata() and once in the page prefetch. This results in duplicate bridge.get_post API calls.
Root Cause
In apps/blog/app/[param]/[p2]/[permlink]/layout.tsx:
// generateMetadata() - Line ~28-31
export async function generateMetadata({ params }: PostPageLayoutProps): Promise<Metadata> {
// ...
const post = await getPost(author, permlink, DEFAULT_OBSERVER); // FIRST CALL
// ... uses post for OG metadata (title, description, image)
}
In apps/blog/app/[param]/[p2]/[permlink]/page.tsx:
// Page component - Line ~36-42
export default async function PostPage({ params, searchParams }: PostPageProps) {
// ...
await queryClient.prefetchQuery({
queryKey: ['postData', username, permlink],
queryFn: () => getPost(username, permlink, observer) // SECOND CALL (same post!)
});
// ...
}
Evidence from Production Logs
Error logs from blog.openhive.network show multiple get_post calls in generateMetadata for the same page request:
Error in generateMetadata: bridge.get_post @author/permlink
Error in generateMetadata: bridge.get_post @author/permlink2
This confirms the duplication is happening in production.
Why React Query Doesn't Deduplicate This
-
generateMetadata()inlayout.tsxruns independently - It calls
getPost()directly (not through React Query) - The
page.tsxthen callsprefetchQuery()with the same function - No request-level deduplication between layout and page
Impact
-
1 duplicate API call per post page visit:
-
bridge.get_postcalled twice for same author/permlink
-
- Adds ~100-300ms latency per post page
- Increases API load
Proposed Fix
Use Next.js cache() to deduplicate at the request level:
// In apps/blog/lib/cached-api.ts
import { cache } from 'react';
import { getPost } from '@transaction/lib/bridge-api';
export const getPostCached = cache(getPost);
Then use getPostCached in both layout.tsx generateMetadata and page.tsx prefetch.
Alternative Consideration
Could also restructure to only fetch in one place:
- Fetch only in page, use for both rendering and metadata
- But this requires restructuring Next.js metadata generation
The cache() approach is simpler and doesn't require architectural changes.
Related
- #794 (closed) - Deduplicate getAccountFull calls in profile page
- #793 (closed) - Remove duplicate community data prefetching
- #790 (closed) - Remove unnecessary SSR prefetch for user subscriptions
- #764 - Current API calls are sub-optimal for denser needs
- NOTES/05-api-call-comparison-results.md - Full API comparison analysis