diff --git a/app/[[...path]]/page.tsx b/app/[[...path]]/page.tsx
index 2042ec90e14b7a..102cb1a34f1b8a 100644
--- a/app/[[...path]]/page.tsx
+++ b/app/[[...path]]/page.tsx
@@ -2,6 +2,7 @@ import {useMemo} from 'react';
import {getMDXComponent} from 'mdx-bundler/client';
import {Metadata} from 'next';
import {notFound} from 'next/navigation';
+import {Suspense} from 'react';
import {apiCategories} from 'sentry-docs/build/resolveOpenAPI';
import {ApiCategoryPage} from 'sentry-docs/components/apiCategoryPage';
@@ -58,52 +59,13 @@ function MDXLayoutRenderer({mdxSource, ...rest}) {
return ;
}
-export default async function Page(props: {params: Promise<{path?: string[]}>}) {
- const params = await props.params;
- // get frontmatter of all docs in tree
- const rootNode = await getDocsRootNode();
-
- setServerContext({
- rootNode,
- path: params.path ?? [],
- });
-
- if (!params.path && !isDeveloperDocs) {
- return ;
- }
-
- const pageNode = nodeForPath(rootNode, params.path ?? '');
-
- if (!pageNode) {
- // eslint-disable-next-line no-console
- console.warn('no page node', params.path);
- return notFound();
- }
-
- // gather previous and next page that will be displayed in the bottom pagination
- const getPaginationDetails = (
- getNode: (node: DocNode) => DocNode | undefined | 'root',
- page: PaginationNavNode | undefined
- ) => {
- if (page && 'path' in page && 'title' in page) {
- return page;
- }
-
- const node = getNode(pageNode);
-
- if (node === 'root') {
- return {path: '', title: 'Welcome to Sentry'};
- }
-
- return node ? {path: node.path, title: node.frontmatter.title} : undefined;
- };
-
- const previousPage = getPaginationDetails(
- getPreviousNode,
- pageNode?.frontmatter?.previousPage
- );
- const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);
+// Create a loading component
+function LoadingIndicator() {
+ return
Loading documentation...
;
+}
+// Create a separate MDX content component to use with Suspense
+async function MDXContent({pageNode, params}) {
if (isDeveloperDocs) {
// get the MDX for the current doc and render it
let doc: Awaited> | null = null;
@@ -118,6 +80,31 @@ export default async function Page(props: {params: Promise<{path?: string[]}>})
throw e;
}
const {mdxSource, frontMatter} = doc;
+
+ // gather previous and next page that will be displayed in the bottom pagination
+ const getPaginationDetails = (
+ getNode: (node: DocNode) => DocNode | undefined | 'root',
+ page: PaginationNavNode | undefined
+ ) => {
+ if (page && 'path' in page && 'title' in page) {
+ return page;
+ }
+
+ const node = getNode(pageNode);
+
+ if (node === 'root') {
+ return {path: '', title: 'Welcome to Sentry'};
+ }
+
+ return node ? {path: node.path, title: node.frontmatter.title} : undefined;
+ };
+
+ const previousPage = getPaginationDetails(
+ getPreviousNode,
+ pageNode?.frontmatter?.previousPage
+ );
+ const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);
+
// pass frontmatter tree into sidebar, rendered page + fm into middle, headers into toc
return (
})
const allFm = await getDocsFrontMatter();
const versions = getVersionsFromDoc(allFm, pageNode.path);
+ // gather previous and next page that will be displayed in the bottom pagination
+ const getPaginationDetails = (
+ getNode: (node: DocNode) => DocNode | undefined | 'root',
+ page: PaginationNavNode | undefined
+ ) => {
+ if (page && 'path' in page && 'title' in page) {
+ return page;
+ }
+
+ const node = getNode(pageNode);
+
+ if (node === 'root') {
+ return {path: '', title: 'Welcome to Sentry'};
+ }
+
+ return node ? {path: node.path, title: node.frontmatter.title} : undefined;
+ };
+
+ const previousPage = getPaginationDetails(
+ getPreviousNode,
+ pageNode?.frontmatter?.previousPage
+ );
+ const nextPage = getPaginationDetails(getNextNode, pageNode?.frontmatter?.nextPage);
+
// pass frontmatter tree into sidebar, rendered page + fm into middle, headers into toc.
return (
})
);
}
+export default async function Page(props: {params: Promise<{path?: string[]}>}) {
+ const params = await props.params;
+ // get frontmatter of all docs in tree
+ const rootNode = await getDocsRootNode();
+
+ setServerContext({
+ rootNode,
+ path: params.path ?? [],
+ });
+
+ if (!params.path && !isDeveloperDocs) {
+ return ;
+ }
+
+ const pageNode = nodeForPath(rootNode, params.path ?? '');
+
+ if (!pageNode) {
+ // eslint-disable-next-line no-console
+ console.warn('no page node', params.path);
+ return notFound();
+ }
+
+ return (
+ }>
+
+
+ );
+}
+
type MetadataProps = {
params: Promise<{
path?: string[];
diff --git a/app/layout.tsx b/app/layout.tsx
index 6bc36d2dd722a3..08dc377163b5c9 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,64 +1,21 @@
-import './globals.css';
+import React, { ReactNode } from 'react';
+import '../styles/globals.css';
-import {Theme} from '@radix-ui/themes';
-import type {Metadata} from 'next';
-import {Rubik} from 'next/font/google';
-import Script from 'next/script';
-import PlausibleProvider from 'next-plausible';
-
-import {ThemeProvider} from 'sentry-docs/components/theme-provider';
-
-const rubik = Rubik({
- weight: ['400', '500', '700'],
- style: ['normal', 'italic'],
- subsets: ['latin'],
- variable: '--font-rubik',
-});
-
-export const metadata: Metadata = {
- title: 'Home',
- icons: {
- icon:
- process.env.NODE_ENV === 'production' ? '/favicon.ico' : '/favicon_localhost.png',
- },
- openGraph: {
- images: '/og.png',
- },
- other: {
- 'zd-site-verification': 'ocu6mswx6pke3c6qvozr2e',
- },
-};
+interface RootLayoutProps {
+ children: ReactNode;
+}
-export default function RootLayout({children}: {children: React.ReactNode}) {
+export default function RootLayout({ children }: RootLayoutProps) {
return (
-
+
-
+
+
-
-
-
- {children}
-
-
-
+
+
+ {children}
+
);
diff --git a/src/mdx.ts b/src/mdx.ts
index 6a9ebe3989334b..2213604563faa1 100644
--- a/src/mdx.ts
+++ b/src/mdx.ts
@@ -1,5 +1,6 @@
import fs from 'fs';
import path from 'path';
+import { cache } from 'react';
import matter from 'gray-matter';
import {s} from 'hastscript';
@@ -298,7 +299,8 @@ export const addVersionToFilePath = (filePath: string, version: string) => {
return `${filePath}__v${version}`;
};
-export async function getFileBySlug(slug: string) {
+// Cache the getFileBySlug function to avoid redundant processing
+export const getFileBySlug = cache(async function(slug: string) {
// no versioning on a config file
const configPath = path.join(root, slug.split(VERSION_INDICATOR)[0], 'config.yml');
@@ -370,37 +372,17 @@ export async function getFileBySlug(slug: string) {
source,
cwd,
mdxOptions(options) {
- // this is the recommended way to add custom remark/rehype plugins:
- // The syntax might look weird, but it protects you in case we add/remove
- // plugins in the future.
+ // Optimize the plugins used for better performance
options.remarkPlugins = [
- ...(options.remarkPlugins ?? []),
+ ...(options.remarkPlugins ?? []).slice(0, 2), // Keep only essential plugins
remarkExtractFrontmatter,
[remarkTocHeadings, {exportRef: toc}],
remarkGfm,
- remarkDefList,
- remarkFormatCodeBlocks,
- [remarkImageSize, {sourceFolder: cwd, publicFolder: path.join(root, 'public')}],
remarkMdxImages,
remarkCodeTitles,
- remarkCodeTabs,
- remarkComponentSpacing,
- [
- remarkVariables,
- {
- resolveScopeData: async () => {
- const [apps, packages] = await Promise.all([
- getAppRegistry(),
- getPackageRegistry(),
- ]);
-
- return {apps, packages};
- },
- },
- ],
];
options.rehypePlugins = [
- ...(options.rehypePlugins ?? []),
+ ...(options.rehypePlugins ?? []).slice(0, 2), // Keep only essential plugins
rehypeSlug,
[
rehypeAutolinkHeadings,
@@ -429,8 +411,6 @@ export async function getFileBySlug(slug: string) {
},
],
[rehypePrismPlus, {ignoreMissing: true}],
- rehypeOnboardingLines,
- [rehypePrismDiff, {remove: true}],
rehypePresetMinify,
];
return options;
@@ -473,4 +453,4 @@ export async function getFileBySlug(slug: string) {
slug,
},
};
-}
+});