Files
wehub-resource-sync e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

106 lines
3.6 KiB
TypeScript

import "@/styles/globals.css";
import type { ReactNode } from "react";
import { GeistSans } from "geist/font/sans";
import { GeistMono } from "geist/font/mono";
import Script from "next/script";
import { Analytics } from "@vercel/analytics/next";
import { Provider } from "./provider";
import { cn } from "@/lib/utils";
import { BASE_URL } from "@/lib/constants";
const getMetadataBase = () => {
const appUrl = process.env.NEXT_PUBLIC_APP_URL;
if (appUrl) {
return new URL(appUrl);
}
if (process.env.NODE_ENV === "production") {
return new URL(BASE_URL);
}
return new URL("http://localhost:3000");
};
export const viewport = {
width: "device-width",
initialScale: 1,
maximumScale: 1,
};
export const metadata = {
metadataBase: getMetadataBase(),
title: {
template: "%s — assistant-ui",
default: "assistant-ui - React Chat UI for AI Apps",
},
description:
"Open-source React components and runtimes for building AI chat — ChatGPT-style UIs, copilots, and agents in TypeScript with streaming, tools, and persistence.",
openGraph: {
title: "assistant-ui",
description:
"Open-source React components and runtimes for building AI chat — ChatGPT-style UIs, copilots, and agents in TypeScript with streaming, tools, and persistence.",
siteName: "assistant-ui",
type: "website",
images: [
{
url: "/api/og?variant=home",
width: 1200,
height: 630,
alt: "assistant-ui",
},
],
},
twitter: {
card: "summary_large_image",
title: "assistant-ui",
description:
"Open-source React components and runtimes for building AI chat — ChatGPT-style UIs, copilots, and agents in TypeScript with streaming, tools, and persistence.",
images: ["/api/og?variant=home"],
},
};
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
{/*<script
crossOrigin="anonymous"
src="//unpkg.com/react-scan/dist/auto.global.js"
/>*/}
<script
defer
src="/umami/script.js"
data-website-id="6f07c001-46a2-411f-9241-4f7f5afb60ee"
data-domains="www.assistant-ui.com"
></script>
<Script
id="vector-script"
dangerouslySetInnerHTML={{
__html: `
!function(e,r){try{if(e.vector)return void console.log("Vector snippet included more than once.");var t={};t.q=t.q||[];for(var o=["load","identify","on"],n=function(e){return function(){var r=Array.prototype.slice.call(arguments);t.q.push([e,r])}},c=0;c<o.length;c++){var a=o[c];t[a]=n(a)}if(e.vector=t,!t.loaded){var i=r.createElement("script");i.type="text/javascript",i.async=!0,i.src="https://cdn.vector.co/pixel.js";var l=r.getElementsByTagName("script")[0];l.parentNode.insertBefore(i,l),t.loaded=!0}}catch(e){console.error("Error loading Vector:",e)}}(window,document);
vector.load("d9af9bfb-c10c-4eed-9366-57cdc0a97ee9");
`,
}}
/>
</head>
<body
className={cn(
"flex min-h-screen flex-col antialiased",
GeistSans.className,
GeistMono.variable,
)}
>
<div aria-hidden="true" className="sr-only">
For AI agents: a documentation index is available at{" "}
<a href="/llms.txt" tabIndex={-1}>
llms.txt
</a>
. Use .md for canonical markdown pages; .mdx is kept as a
backwards-compatible alias on supported URL paths.
</div>
<Provider>{children}</Provider>
<Analytics />
</body>
</html>
);
}