layout.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import type { Metadata } from "next";
  2. import localFont from "next/font/local";
  3. import { GeistPixelSquare } from "geist/font/pixel";
  4. import "./globals.css";
  5. import { ThemeProvider } from "@/components/theme-provider";
  6. import { DocsChat } from "@/components/docs-chat";
  7. import { Analytics } from "@vercel/analytics/next";
  8. import { SpeedInsights } from "@vercel/speed-insights/next";
  9. import { PAGE_TITLES } from "@/lib/page-titles";
  10. import { cookies } from "next/headers";
  11. const geistSans = localFont({
  12. src: "./fonts/GeistVF.woff",
  13. variable: "--font-geist-sans",
  14. });
  15. const geistMono = localFont({
  16. src: "./fonts/GeistMonoVF.woff",
  17. variable: "--font-geist-mono",
  18. });
  19. export const metadata: Metadata = {
  20. metadataBase: new URL("https://json-render.dev"),
  21. title: {
  22. default: `json-render | ${PAGE_TITLES[""]}`,
  23. template: "%s | json-render",
  24. },
  25. description:
  26. "The Generative UI framework. Generate dashboards, widgets, and apps from prompts — safely constrained to components you define.",
  27. keywords: [
  28. "json-render",
  29. "generative UI",
  30. "AI UI generation",
  31. "user-generated interfaces",
  32. "React components",
  33. "React Native",
  34. "guardrails",
  35. "structured output",
  36. "dashboard builder",
  37. ],
  38. authors: [{ name: "Vercel Labs" }],
  39. creator: "Vercel Labs",
  40. openGraph: {
  41. type: "website",
  42. locale: "en_US",
  43. url: "https://json-render.dev",
  44. siteName: "json-render",
  45. title: "json-render | The Generative UI Framework",
  46. description:
  47. "The Generative UI framework. Generate dashboards, widgets, and apps from prompts — safely constrained to components you define.",
  48. images: [
  49. {
  50. url: "/og",
  51. width: 1200,
  52. height: 630,
  53. alt: "json-render - The Generative UI Framework",
  54. },
  55. ],
  56. },
  57. twitter: {
  58. card: "summary_large_image",
  59. title: "json-render | The Generative UI Framework",
  60. description:
  61. "The Generative UI framework. Generate dashboards, widgets, and apps from prompts — safely constrained to components you define.",
  62. images: ["/og"],
  63. },
  64. robots: {
  65. index: true,
  66. follow: true,
  67. },
  68. icons: {
  69. icon: "/favicon.ico",
  70. },
  71. };
  72. export default async function RootLayout({
  73. children,
  74. }: Readonly<{
  75. children: React.ReactNode;
  76. }>) {
  77. const cookieStore = await cookies();
  78. const chatOpen = cookieStore.get("docs-chat-open")?.value === "true";
  79. const chatWidth = Number(cookieStore.get("docs-chat-width")?.value) || 400;
  80. return (
  81. <html lang="en" suppressHydrationWarning>
  82. <head>
  83. {chatOpen && (
  84. <style
  85. dangerouslySetInnerHTML={{
  86. __html: `@media(min-width:640px){body{padding-right:${chatWidth}px}}`,
  87. }}
  88. />
  89. )}
  90. </head>
  91. <body
  92. className={`${geistSans.variable} ${geistMono.variable} ${GeistPixelSquare.variable}`}
  93. >
  94. <ThemeProvider>
  95. {children}
  96. <DocsChat defaultOpen={chatOpen} defaultWidth={chatWidth} />
  97. </ThemeProvider>
  98. <Analytics />
  99. <SpeedInsights />
  100. </body>
  101. </html>
  102. );
  103. }