Skip to content

Commit ede1b43

Browse files
committed
review: address PR feedback
From Copilot's automated review on PR #8492: - layout.tsx: render `<meta property="fb:app_id">` as a property tag directly in <head> (Next's `metadata.other` only emits name=). - layout.tsx: restore the RSS autodiscovery <link> and the Algolia preconnect <link> that lived in the old Pages Router <Head>. - readMarkdownPage.ts: switch readFileSync -> fs.promises.readFile to avoid blocking the event loop while compiling MDX. - package.json: bump @types/node from ^14 to ^20 to match the new engines.node >=20.9.0. - buildPageMetadata.ts + renderSectionPage.tsx + learn/blog generateMetadata: thread the section's routeTree through so we can re-emit the `algolia-search-order` meta tag on Learn pages and Blog posts (matches the old <Seo> behavior; Algolia uses it for ordering).
1 parent 90ae66f commit ede1b43

9 files changed

Lines changed: 63 additions & 12 deletions

File tree

next-env.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3-
import "./.next/types/routes.d.ts";
4-
import "./.next/types/root-params.d.ts";
3+
import "./.next/dev/types/routes.d.ts";
4+
import "./.next/dev/types/root-params.d.ts";
55

66
// NOTE: This file should not be edited
77
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"@types/debounce": "^1.2.1",
5656
"@types/github-slugger": "^1.3.0",
5757
"@types/mdx-js__react": "^1.5.2",
58-
"@types/node": "^14.6.4",
58+
"@types/node": "^20",
5959
"@types/parse-numeric-range": "^0.0.1",
6060
"@types/prop-types": "^15.7.15",
6161
"@types/react": "19.2.17",

src/app/blog/[[...slug]]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function generateMetadata({params}: PageProps): Promise<Metadata> {
2626
return sectionPageMetadata({
2727
section: 'blog',
2828
segments: ['blog', ...(slug ?? [])],
29+
routeTree: sidebarBlog as RouteItem,
2930
});
3031
}
3132

src/app/layout.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ export const metadata: Metadata = {
3939
],
4040
},
4141
manifest: '/site.webmanifest',
42+
// Items here render as `<meta name="...">`. Property-style tags
43+
// (`<meta property="...">`) like `fb:app_id` must be rendered directly
44+
// in `<head>` below, since Next's `metadata.other` only emits `name=`.
4245
other: {
4346
'msapplication-TileColor': '#2b5797',
44-
'fb:app_id': '623268441017527',
4547
'google-site-verification': 'sIlAGs48RulR4DdP95YSWNKZIEtCqQmRjzn-Zq-CcD0',
4648
},
4749
};
@@ -161,6 +163,21 @@ export default function RootLayout({children}: {children: React.ReactNode}) {
161163
return (
162164
<html lang={siteConfig.languageCode} dir={siteConfig.isRTL ? 'rtl' : 'ltr'}>
163165
<head>
166+
{/* RSS autodiscovery */}
167+
<link
168+
rel="alternate"
169+
type="application/rss+xml"
170+
title="React Blog RSS Feed"
171+
href="/rss.xml"
172+
/>
173+
{/* Preconnect to Algolia DocSearch for faster first-open search */}
174+
<link
175+
rel="preconnect"
176+
href={`https://${siteConfig.algolia.appId}-dsn.algolia.net`}
177+
/>
178+
{/* Facebook app id is a property-style meta tag and can't be expressed
179+
via Next's `metadata.other`, which emits `name=` tags. */}
180+
<meta property="fb:app_id" content="623268441017527" />
164181
{FONT_PRELOADS.map((file) => (
165182
<link
166183
key={file}

src/app/learn/[[...slug]]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function generateMetadata({params}: PageProps): Promise<Metadata> {
2626
return sectionPageMetadata({
2727
section: 'learn',
2828
segments: ['learn', ...(slug ?? [])],
29+
routeTree: sidebarLearn as RouteItem,
2930
});
3031
}
3132

src/app/renderSectionPage.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ export async function renderSectionPage({
4141
export async function sectionPageMetadata({
4242
segments,
4343
section,
44+
routeTree,
4445
}: {
4546
segments: string[];
4647
section: PageSection;
48+
routeTree?: RouteItem;
4749
}): Promise<Metadata> {
4850
const data = await safeReadPage(segments);
4951
if (!data) return {};
5052
const pathname = '/' + segments.join('/');
51-
return buildPageMetadata({data, pathname, section});
53+
return buildPageMetadata({data, pathname, section, routeTree});
5254
}
5355

5456
async function safeReadPage(segments: string[]) {

src/lib/buildPageMetadata.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import type {Metadata} from 'next';
99
import {siteConfig} from '../siteConfig';
1010
import {finishedTranslations} from 'utils/finishedTranslations';
11+
import {getRouteMeta, type RouteItem} from 'components/Layout/getRouteMeta';
1112
import type {PageData} from './readMarkdownPage';
1213
import type {PageSection} from 'components/Layout/Page';
1314

@@ -20,12 +21,19 @@ export function buildPageMetadata({
2021
data,
2122
pathname,
2223
section,
24+
routeTree,
2325
}: {
2426
data: PageData;
2527
pathname: string;
2628
section: PageSection;
29+
/**
30+
* Optional sidebar tree, used to compute the Algolia `algolia-search-order`
31+
* meta tag for Learn/Blog pages. Omit for routes outside those sections.
32+
*/
33+
routeTree?: RouteItem;
2734
}): Metadata {
2835
const isHomePage = pathname === '/';
36+
const isBlogIndex = section === 'blog' && pathname === '/blog';
2937
const title = data.meta.title || '';
3038
const titleForTitleTag = data.meta.titleForTitleTag;
3139
const pageTitle =
@@ -49,6 +57,20 @@ export function buildPageMetadata({
4957
languages[code] = canonicalUrl.replace(siteDomain, getDomain(code));
5058
}
5159

60+
// Match the Pages Router behavior: emit `algolia-search-order` on Learn
61+
// pages and Blog post pages (not the Blog index) so Algolia can preserve
62+
// the docs sidebar ordering in search results.
63+
const other: Record<string, string> = {};
64+
if (
65+
routeTree &&
66+
(section === 'learn' || (section === 'blog' && !isBlogIndex))
67+
) {
68+
const {order} = getRouteMeta(pathname, routeTree);
69+
if (order != null) {
70+
other['algolia-search-order'] = String(order);
71+
}
72+
}
73+
5274
return {
5375
title: pageTitle,
5476
description: isHomePage ? description : undefined,
@@ -71,5 +93,6 @@ export function buildPageMetadata({
7193
description,
7294
images: [ogImage],
7395
},
96+
other: Object.keys(other).length > 0 ? other : undefined,
7497
};
7598
}

src/lib/readMarkdownPage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import 'server-only';
9-
import fs from 'fs';
9+
import fs from 'fs/promises';
1010
import path from 'path';
1111
import compileMDX from 'utils/compileMDX';
1212

@@ -27,9 +27,9 @@ export async function readMarkdownPage(segments: string[]): Promise<PageData> {
2727
const routePath = segments.join('/') || 'index';
2828
let mdx: string;
2929
try {
30-
mdx = fs.readFileSync(path.join(ROOT, routePath + '.md'), 'utf8');
30+
mdx = await fs.readFile(path.join(ROOT, routePath + '.md'), 'utf8');
3131
} catch {
32-
mdx = fs.readFileSync(path.join(ROOT, routePath, 'index.md'), 'utf8');
32+
mdx = await fs.readFile(path.join(ROOT, routePath, 'index.md'), 'utf8');
3333
}
3434
const {toc, content, meta, languages} = await compileMDX(mdx, routePath, {});
3535
return {toc, content, meta, languages};

yarn.lock

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,10 +1912,12 @@
19121912
resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz"
19131913
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
19141914

1915-
"@types/node@^14.6.4":
1916-
version "14.18.9"
1917-
resolved "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz"
1918-
integrity sha512-j11XSuRuAlft6vLDEX4RvhqC0KxNxx6QIyMXNb0vHHSNPXTPeiy3algESWmOOIzEtiEL0qiowPU3ewW9hHVa7Q==
1915+
"@types/node@^20":
1916+
version "20.19.43"
1917+
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.43.tgz#fcecf580ba42a0db55cf404c372c97973c376c97"
1918+
integrity sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==
1919+
dependencies:
1920+
undici-types "~6.21.0"
19191921

19201922
"@types/parse-numeric-range@^0.0.1":
19211923
version "0.0.1"
@@ -8901,6 +8903,11 @@ unbox-primitive@^1.1.0:
89018903
has-symbols "^1.1.0"
89028904
which-boxed-primitive "^1.1.1"
89038905

8906+
undici-types@~6.21.0:
8907+
version "6.21.0"
8908+
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
8909+
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
8910+
89048911
unherit@^1.0.4:
89058912
version "1.1.3"
89068913
resolved "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz"

0 commit comments

Comments
 (0)