layout.tsx 2.9 KB

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