Skip to content

Commit 1c063f7

Browse files
Add: server side metadata generation in root layout (#755)
- adds `generateMetadata` in root layout to generate canonical and robots meta tags server side - listens on a custom header which is set by our proxy before rewriting `/docs` routes, to decide whether the document should have no-index metadata or index metadata - adds a middleware which appends a custom header to retrieve the current pathname for server side canonical tag generation
1 parent f1afba0 commit 1c063f7

4 files changed

Lines changed: 80 additions & 31 deletions

File tree

apps/web/src/app/layout.tsx

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,63 @@
11
import { Metadata } from 'next'
22
import { Analytics } from '@vercel/analytics/react'
33
import Script from 'next/script'
4-
54
import { Providers } from '@/app/providers'
6-
75
import '@/styles/tailwind.css'
8-
import Canonical from '@/components/Navigation/canonical'
96
import { Header } from '@/components/Header'
107
import glob from 'fast-glob'
118
import { Section } from '@/components/SectionProvider'
129
import { Layout } from '@/components/Layout'
10+
import { headers } from 'next/headers'
1311

14-
export const metadata: Metadata = {
15-
title: {
16-
template: '%s - E2B',
17-
default: 'E2B - Code Interpreting for AI apps',
18-
},
19-
description: 'Open-source secure sandboxes for AI code execution',
20-
twitter: {
21-
title: 'E2B - Code Interpreting for AI apps',
22-
description: 'Open-source secure sandboxes for AI code execution',
23-
},
24-
openGraph: {
25-
title: 'E2B - Code Interpreting for AI apps',
12+
async function isValidPath(pathname: string) {
13+
try {
14+
const docsDirectory = await glob('**/*.mdx', {
15+
cwd: `src/app/(docs)${pathname}`,
16+
})
17+
18+
return docsDirectory.length > 0
19+
} catch (error) {
20+
console.error('Error validating path in generateMetadata:', error)
21+
return false
22+
}
23+
}
24+
25+
export async function generateMetadata() {
26+
const headerList = headers()
27+
const pathname = headerList.get('x-middleware-pathname')
28+
const shouldIndex = headerList.get('x-e2b-should-index')
29+
30+
let isValid = false
31+
32+
if (pathname?.startsWith('/docs')) {
33+
isValid = await isValidPath(pathname)
34+
}
35+
36+
return {
37+
title: {
38+
template: '%s - E2B',
39+
default: 'E2B - Code Interpreting for AI apps',
40+
},
2641
description: 'Open-source secure sandboxes for AI code execution',
27-
},
42+
twitter: {
43+
title: 'E2B - Code Interpreting for AI apps',
44+
description: 'Open-source secure sandboxes for AI code execution',
45+
},
46+
openGraph: {
47+
title: 'E2B - Code Interpreting for AI apps',
48+
description: 'Open-source secure sandboxes for AI code execution',
49+
},
50+
alternates:
51+
isValid && pathname !== ''
52+
? {
53+
canonical: `https://e2b.dev${pathname}`,
54+
}
55+
: undefined,
56+
robots:
57+
isValid && shouldIndex
58+
? { index: true, follow: true }
59+
: { index: false, follow: false },
60+
} satisfies Metadata
2861
}
2962

3063
declare global {
@@ -60,7 +93,6 @@ export default async function RootLayout({ children }) {
6093
`}
6194
</Script>
6295
)}
63-
<Canonical />
6496
</head>
6597
<body className="flex min-h-full antialiased bg-zinc-900">
6698
{process.env.NODE_ENV === 'production' && (

apps/web/src/app/not-found.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@ import Link from 'next/link'
22

33
export default function NotFound() {
44
return (
5-
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100vh' }}>
5+
<div
6+
style={{
7+
display: 'flex',
8+
flexDirection: 'column',
9+
alignItems: 'center',
10+
justifyContent: 'center',
11+
height: '100vh',
12+
}}
13+
>
614
<h2>Not Found</h2>
715
<p>Could not find requested resource</p>
8-
<Link href="/" style={{ textDecoration: 'underline', color: '#ff8800' }}>Return Home</Link>
16+
<Link href="/" style={{ textDecoration: 'underline', color: '#ff8800' }}>
17+
Return Home
18+
</Link>
919
</div>
1020
)
1121
}

apps/web/src/components/Navigation/canonical.tsx

Lines changed: 0 additions & 12 deletions
This file was deleted.

apps/web/src/middleware.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { NextResponse } from 'next/server'
2+
import type { NextRequest } from 'next/server'
3+
4+
export function middleware(request: NextRequest) {
5+
const path = request.nextUrl.pathname
6+
7+
const requestHeaders = new Headers(request.headers)
8+
requestHeaders.set('x-middleware-pathname', path)
9+
10+
return NextResponse.next({
11+
request: {
12+
headers: requestHeaders,
13+
},
14+
})
15+
}
16+
17+
export const config = {
18+
matcher: '/docs/:path*',
19+
}

0 commit comments

Comments
 (0)