diff --git a/apps/site/app/[locale]/layout.tsx b/apps/site/app/[locale]/layout.tsx index ed0a60eb0057e..3faa14079216a 100644 --- a/apps/site/app/[locale]/layout.tsx +++ b/apps/site/app/[locale]/layout.tsx @@ -14,9 +14,11 @@ import '#site/styles/index.css'; const fontClasses = classNames(IBM_PLEX_MONO.variable, OPEN_SANS.variable); -type RotLayoutProps = PropsWithChildren<{ params: { locale: string } }>; +type RootLayoutProps = PropsWithChildren<{ + params: Promise<{ locale: string }>; +}>; -const RootLayout: FC = async ({ children, params }) => { +const RootLayout: FC = async ({ children, params }) => { const { locale } = await params; const { langDir, hrefLang } = availableLocalesMap[locale] || defaultLocale; diff --git a/apps/site/app/[locale]/next-data/api-data/route.ts b/apps/site/app/[locale]/next-data/api-data/route.ts index 4ba97056079e4..2e469ec77f717 100644 --- a/apps/site/app/[locale]/next-data/api-data/route.ts +++ b/apps/site/app/[locale]/next-data/api-data/route.ts @@ -32,31 +32,40 @@ export const GET = async () => { authorizationHeaders ); - return gitHubApiResponse.json().then((apiDocsFiles: Array) => { - // maps over each api file and get the download_url, fetch the content and deflates it - const mappedApiFiles = apiDocsFiles.map( - async ({ name, path: filename, download_url }) => { - const apiFileResponse = await fetch(download_url); - - // Retrieves the content as a raw text string - const source = await apiFileResponse.text(); - - // Removes empty/blank lines or lines just with spaces and trims each line - // from leading and trailing paddings/spaces - const cleanedContent = parseRichTextIntoPlainText(source); - - const deflatedSource = deflateSync(cleanedContent).toString('base64'); - - return { - filename: filename, - pathname: getPathnameForApiFile(name, versionWithPrefix), - content: deflatedSource, - }; - } - ); - - return Promise.all(mappedApiFiles).then(Response.json); - }); + // transforms the response into an array of GitHubApiFile + const apiDocsFiles: Array = await gitHubApiResponse.json(); + + // prevent the route from crashing if the response is not an array of GitHubApiFile + // and return an empty array instead. This is a fallback for when the GitHub API is not available. + if (!Array.isArray(apiDocsFiles)) { + return Response.json([]); + } + + // maps over each api file and get the download_url, fetch the content and deflates it + const mappedApiFiles = apiDocsFiles.map( + async ({ name, path: filename, download_url }) => { + const apiFileResponse = await fetch(download_url); + + // Retrieves the content as a raw text string + const source = await apiFileResponse.text(); + + // Removes empty/blank lines or lines just with spaces and trims each line + // from leading and trailing paddings/spaces + const cleanedContent = parseRichTextIntoPlainText(source); + + const deflatedSource = deflateSync(cleanedContent).toString('base64'); + + return { + filename: filename, + pathname: getPathnameForApiFile(name, versionWithPrefix), + content: deflatedSource, + }; + } + ); + + const data = await Promise.all(mappedApiFiles); + + return Response.json(data); }; // This function generates the static paths that come from the dynamic segments diff --git a/apps/site/app/[locale]/next-data/download-snippets/route.tsx b/apps/site/app/[locale]/next-data/download-snippets/route.tsx deleted file mode 100644 index 90232982a2d45..0000000000000 --- a/apps/site/app/[locale]/next-data/download-snippets/route.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import provideDownloadSnippets from '#site/next-data/providers/downloadSnippets'; -import { defaultLocale } from '#site/next.locales.mjs'; - -type DynamicStaticPaths = { locale: string }; -type StaticParams = { params: Promise }; - -// This is the Route Handler for the `GET` method which handles the request -// for generating JSON data for Download Snippets -// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers -export const GET = async (_: Request, props: StaticParams) => { - const params = await props.params; - - // Retrieve all available Download snippets for a given locale if available - const snippets = provideDownloadSnippets(params.locale); - - // We append always the default/fallback snippets when a result is found - return Response.json(snippets, { - status: snippets !== undefined ? 200 : 404, - }); -}; - -// This function generates the static paths that come from the dynamic segments -// `[locale]/next-data/download-snippets/` this will return a default value as we don't want to -// statically generate this route as it is compute-expensive. -// Hence we generate a fake route just to satisfy Next.js requirements. -export const generateStaticParams = async () => [ - { locale: defaultLocale.code }, -]; - -// Enforces that this route is cached and static as much as possible -// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic -export const dynamic = 'force-static'; - -// Ensures that this endpoint is invalidated and re-executed every X minutes -// so that when new deployments happen, the data is refreshed -// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate -export const revalidate = 300; diff --git a/apps/site/app/[locale]/next-data/page-data/route.ts b/apps/site/app/[locale]/next-data/page-data/route.ts index ff1f155bfdf2b..a9ad5a7e4416c 100644 --- a/apps/site/app/[locale]/next-data/page-data/route.ts +++ b/apps/site/app/[locale]/next-data/page-data/route.ts @@ -10,44 +10,52 @@ import { parseRichTextIntoPlainText } from '#site/util/string'; // for a digest and metadata of all existing pages on Node.js Website // @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers export const GET = async () => { + // Retrieves all available routes for the default locale const allAvailbleRoutes = await dynamicRouter.getRoutesByLanguage( defaultLocale.code ); - const availablePagesMetadata = allAvailbleRoutes - .filter(route => !route.startsWith('blog')) - .map(async pathname => { - const { source, filename } = await dynamicRouter.getMarkdownFile( - defaultLocale.code, - pathname - ); + // We exclude the blog routes from the available pages metadata + // as they are generated separately and are not part of the static pages + // and are not part of the static pages metadata + const routesExceptBlog = allAvailbleRoutes.filter( + route => !route.startsWith('blog') + ); + + const availablePagesMetadata = routesExceptBlog.map(async pathname => { + const { source, filename } = await dynamicRouter.getMarkdownFile( + defaultLocale.code, + pathname + ); + + // Gets the title and the Description from the Page Metadata + const { title, description } = await dynamicRouter.getPageMetadata( + defaultLocale.code, + pathname + ); - // Gets the title and the Description from the Page Metadata - const { title, description } = await dynamicRouter.getPageMetadata( - defaultLocale.code, - pathname - ); + // Parser the Markdown source with `gray-matter` and then only + // grabs the markdown content and cleanses it by removing HTML/JSX tags + // removing empty/blank lines or lines just with spaces and trims each line + // from leading and trailing paddings/spaces + const cleanedContent = parseRichTextIntoPlainText(matter(source).content); - // Parser the Markdown source with `gray-matter` and then only - // grabs the markdown content and cleanses it by removing HTML/JSX tags - // removing empty/blank lines or lines just with spaces and trims each line - // from leading and trailing paddings/spaces - const cleanedContent = parseRichTextIntoPlainText(matter(source).content); + // Deflates a String into a base64 string-encoded (zlib compressed) + const content = deflateSync(cleanedContent).toString('base64'); - // Deflates a String into a base64 string-encoded (zlib compressed) - const content = deflateSync(cleanedContent).toString('base64'); + // Returns metadata of each page available on the Website + return { + filename, + pathname, + title, + description, + content, + }; + }); - // Returns metadata of each page available on the Website - return { - filename, - pathname, - title, - description, - content, - }; - }); + const data = await Promise.all(availablePagesMetadata); - return Response.json(await Promise.all(availablePagesMetadata)); + return Response.json(data); }; // This function generates the static paths that come from the dynamic segments diff --git a/apps/site/app/[locale]/next-data/release-data/route.ts b/apps/site/app/[locale]/next-data/release-data/route.ts deleted file mode 100644 index 8b4d229f81066..0000000000000 --- a/apps/site/app/[locale]/next-data/release-data/route.ts +++ /dev/null @@ -1,31 +0,0 @@ -import provideReleaseData from '#site/next-data/providers/releaseData'; -import { defaultLocale } from '#site/next.locales.mjs'; - -// This is the Route Handler for the `GET` method which handles the request -// for generating static data related to the Node.js Release Data -// @see https://nextjs.org/docs/app/building-your-application/routing/router-handlers -export const GET = async () => { - const releaseData = provideReleaseData(); - - return Response.json(releaseData); -}; - -// This function generates the static paths that come from the dynamic segments -// `[locale]/next-data/release-data/` and returns an array of all available static paths -// This is used for ISR static validation and generation -export const generateStaticParams = async () => [ - { locale: defaultLocale.code }, -]; - -// Enforces that only the paths from `generateStaticParams` are allowed, giving 404 on the contrary -// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamicparams -export const dynamicParams = false; - -// Enforces that this route is used as static rendering -// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic -export const dynamic = 'error'; - -// Ensures that this endpoint is invalidated and re-executed every X minutes -// so that when new deployments happen, the data is refreshed -// @see https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#revalidate -export const revalidate = 300; diff --git a/apps/site/app/[locale]/not-found.tsx b/apps/site/app/[locale]/not-found.tsx index 7972f7c265ac4..2caeb07a589f1 100644 --- a/apps/site/app/[locale]/not-found.tsx +++ b/apps/site/app/[locale]/not-found.tsx @@ -13,10 +13,12 @@ const NotFoundPage: FC = () => { return ( - 404 + 404 +

{t('layouts.error.notFound.title')}

+
{ />
+

{t('layouts.error.notFound.description')}

+