|
1 | | -import type { Metadata } from "next"; |
| 1 | +import { getDictionary } from "@/_dictionaries/get-dictionary"; |
| 2 | +import { SignupLink } from "@/app/_components/analytics"; |
| 3 | +import CustomLayout from "@/app/_components/custom-layout"; |
| 4 | +import { Footer } from "@/app/_components/footer"; |
| 5 | +import { Logo } from "@/app/_components/logo"; |
| 6 | +import NavBarButton from "@/app/_components/nav-bar-button"; |
| 7 | +import { TranslationBanner } from "@/app/_components/translation-banner"; |
| 8 | +import "@/app/globals.css"; |
| 9 | +import { Discord, Github } from "@arcadeai/design-system"; |
| 10 | +import { GoogleTagManager } from "@next/third-parties/google"; |
| 11 | +import { headers } from "next/headers"; |
| 12 | +import Link from "next/link"; |
| 13 | +import Script from "next/script"; |
| 14 | +import { Head } from "nextra/components"; |
| 15 | +import { getPageMap } from "nextra/page-map"; |
| 16 | +import { |
| 17 | + LastUpdated, |
| 18 | + Layout, |
| 19 | + Navbar, |
| 20 | + Footer as NextraFooter, |
| 21 | +} from "nextra-theme-docs"; |
| 22 | +import { PostHog } from "./_components/posthog"; |
2 | 23 |
|
3 | | -export const metadata: Metadata = { |
4 | | - title: "Arcade Docs", |
| 24 | +const REGEX_LOCALE = /^\/([a-z]{2}(?:-[A-Z]{2})?)(?:\/|$)/; |
| 25 | + |
| 26 | +export const metadata = { |
| 27 | + title: { |
| 28 | + default: "Arcade Docs", |
| 29 | + template: "%s | Arcade Docs", |
| 30 | + }, |
5 | 31 | description: "Arcade - AI platform for developers", |
| 32 | + metadataBase: new URL("https://docs.arcade.dev"), |
| 33 | + manifest: "/site.webmanifest", |
| 34 | + icons: { |
| 35 | + icon: [ |
| 36 | + { url: "/favicon-16x16.png", sizes: "16x16", type: "image/png" }, |
| 37 | + { url: "/favicon-32x32.png", sizes: "32x32", type: "image/png" }, |
| 38 | + { url: "/favicon.ico" }, |
| 39 | + ], |
| 40 | + apple: { url: "/apple-touch-icon.png", sizes: "180x180" }, |
| 41 | + other: [ |
| 42 | + { rel: "mask-icon", url: "/safari-pinned-tab.svg", color: "#5bbad5" }, |
| 43 | + ], |
| 44 | + }, |
| 45 | + openGraph: { |
| 46 | + type: "website", |
| 47 | + url: "https://docs.arcade.dev", |
| 48 | + siteName: "Arcade Docs", |
| 49 | + images: [ |
| 50 | + { |
| 51 | + url: "/images/logo/arcade-logo.png", |
| 52 | + width: 1200, |
| 53 | + height: 630, |
| 54 | + alt: "Arcade", |
| 55 | + }, |
| 56 | + ], |
| 57 | + }, |
| 58 | + twitter: { |
| 59 | + card: "summary_large_image", |
| 60 | + site: "@TryArcade", |
| 61 | + images: ["/images/logo/arcade-logo.png"], |
| 62 | + }, |
| 63 | + appleWebApp: { |
| 64 | + title: "Arcade Documentation", |
| 65 | + }, |
| 66 | + other: { |
| 67 | + "apple-mobile-web-app-title": "Arcade Documentation", |
| 68 | + "twitter:url": "https://docs.arcade.dev", |
| 69 | + "twitter:site:domain": "docs.arcade.dev", |
| 70 | + }, |
6 | 71 | }; |
7 | 72 |
|
8 | | -export default function RootLayout({ |
| 73 | +function getLocaleFromPathname(pathname: string): string { |
| 74 | + const localeMatch = pathname.match(REGEX_LOCALE); |
| 75 | + return localeMatch?.[1] || "en"; |
| 76 | +} |
| 77 | + |
| 78 | +export default async function RootLayout({ |
9 | 79 | children, |
10 | 80 | }: { |
11 | 81 | children: React.ReactNode; |
12 | 82 | }) { |
13 | | - return children; |
| 83 | + const headersList = await headers(); |
| 84 | + const pathname = headersList.get("x-pathname") || "/"; |
| 85 | + const lang = getLocaleFromPathname(pathname); |
| 86 | + |
| 87 | + const dictionary = await getDictionary(lang); |
| 88 | + const pageMap = await getPageMap(`/${lang}`); |
| 89 | + |
| 90 | + return ( |
| 91 | + <html dir="ltr" lang={lang} suppressHydrationWarning> |
| 92 | + <Head |
| 93 | + backgroundColor={{ |
| 94 | + dark: "#0a0a0a", |
| 95 | + light: "#ffffff", |
| 96 | + }} |
| 97 | + color={{ |
| 98 | + hue: 347, |
| 99 | + saturation: 100, |
| 100 | + lightness: 50, |
| 101 | + }} |
| 102 | + > |
| 103 | + <meta content={lang} httpEquiv="Content-Language" /> |
| 104 | + <meta content="width=device-width, initial-scale=1" name="viewport" /> |
| 105 | + <link href="https://www.googletagmanager.com" rel="preconnect" /> |
| 106 | + <link href="https://www.googletagmanager.com" rel="dns-prefetch" /> |
| 107 | + </Head> |
| 108 | + <body> |
| 109 | + {lang !== "en" && ( |
| 110 | + <TranslationBanner dictionary={dictionary} locale={lang} /> |
| 111 | + )} |
| 112 | + <Layout |
| 113 | + copyPageButton={true} |
| 114 | + docsRepositoryBase="https://github.com/ArcadeAI/docs/tree/main/" |
| 115 | + editLink={dictionary.editPage} |
| 116 | + footer={ |
| 117 | + <NextraFooter> |
| 118 | + <Footer /> |
| 119 | + </NextraFooter> |
| 120 | + } |
| 121 | + i18n={[{ locale: "en", name: "English" }]} |
| 122 | + lastUpdated={<LastUpdated>{dictionary.lastUpdated}</LastUpdated>} |
| 123 | + navbar={ |
| 124 | + <Navbar |
| 125 | + chatIcon={ |
| 126 | + <Discord className="size-6 transition-colors duration-150 ease-in-out [&>path]:fill-current" /> |
| 127 | + } |
| 128 | + chatLink="https://discord.gg/GUZEMpEZ9p" |
| 129 | + logo={<Logo />} |
| 130 | + logoLink={`/${lang}/home`} |
| 131 | + projectIcon={ |
| 132 | + <Github className="size-5.5 transition-colors duration-150 ease-in-out [&>path]:fill-current" /> |
| 133 | + } |
| 134 | + projectLink="https://github.com/ArcadeAI/docs" |
| 135 | + > |
| 136 | + <SignupLink linkLocation="docs:navbar"> |
| 137 | + <NavBarButton |
| 138 | + hideOnPath={["/home/registry-early-access"]} |
| 139 | + text="Sign Up" |
| 140 | + /> |
| 141 | + </SignupLink> |
| 142 | + <Link href="https://api.arcade.dev/dashboard/playground/chat"> |
| 143 | + <NavBarButton text="Dashboard" variant="outline" /> |
| 144 | + </Link> |
| 145 | + </Navbar> |
| 146 | + } |
| 147 | + nextThemes={{ defaultTheme: "dark" }} |
| 148 | + pageMap={pageMap} |
| 149 | + sidebar={{ |
| 150 | + defaultMenuCollapseLevel: 1, |
| 151 | + autoCollapse: true, |
| 152 | + }} |
| 153 | + themeSwitch={{ |
| 154 | + dark: dictionary.dark, |
| 155 | + light: dictionary.light, |
| 156 | + system: dictionary.system, |
| 157 | + }} |
| 158 | + toc={{ |
| 159 | + backToTop: dictionary.toc.backToTop, |
| 160 | + title: dictionary.toc.title, |
| 161 | + }} |
| 162 | + > |
| 163 | + <GoogleTagManager gtmId="GTM-TVS58H5F" /> |
| 164 | + <Script |
| 165 | + src="https://status.arcade.dev/embed/script.js" |
| 166 | + strategy="afterInteractive" |
| 167 | + /> |
| 168 | + <PostHog> |
| 169 | + <CustomLayout>{children}</CustomLayout> |
| 170 | + </PostHog> |
| 171 | + </Layout> |
| 172 | + </body> |
| 173 | + </html> |
| 174 | + ); |
14 | 175 | } |
0 commit comments