import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { baseURL } from "@/baseUrl";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<NextChatSDKBootstrap baseUrl={baseURL} />
</head>
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
function NextChatSDKBootstrap({ baseUrl }: { baseUrl: string }) {
return (
<>
<base href={baseUrl}></base>
<script>{`window.innerBaseUrl = ${JSON.stringify(baseUrl)}`}</script>
<script>{`window.__isChatGptApp = typeof window.openai !== "undefined";`}</script>
<script>
{"(" +
(() => {
const baseUrl = window.innerBaseUrl;
const htmlElement = document.documentElement;
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (
mutation.type === "attributes" &&
mutation.target === htmlElement
) {
const attrName = mutation.attributeName;
if (attrName && attrName !== "suppresshydrationwarning") {
htmlElement.removeAttribute(attrName);
}
}
});
});
observer.observe(htmlElement, {
attributes: true,
attributeOldValue: true,
});
const originalReplaceState = history.replaceState;
history.replaceState = (s, unused, url) => {
const u = new URL(url ?? "", window.location.href);
const href = u.pathname + u.search + u.hash;
originalReplaceState.call(history, unused, href);
};
const originalPushState = history.pushState;
history.pushState = (s, unused, url) => {
const u = new URL(url ?? "", window.location.href);
const href = u.pathname + u.search + u.hash;
originalPushState.call(history, unused, href);
};
const appOrigin = new URL(baseUrl).origin;
const isInIframe = window.self !== window.top;
window.addEventListener(
"click",
(e) => {
const a = (e?.target as HTMLElement)?.closest("a");
if (!a || !a.href) return;
const url = new URL(a.href, window.location.href);
if (
url.origin !== window.location.origin &&
url.origin != appOrigin
) {
try {
if (window.openai) {
window.openai?.openExternal({ href: a.href });
e.preventDefault();
}
} catch {
console.warn(
"openExternal failed, likely not in OpenAI client"
);
}
}
},
true
);
if (isInIframe && window.location.origin !== appOrigin) {
const originalFetch = window.fetch;
window.fetch = (input: URL | RequestInfo, init?: RequestInit) => {
let url: URL;
if (typeof input === "string" || input instanceof URL) {
url = new URL(input, window.location.href);
} else {
url = new URL(input.url, window.location.href);
}
if (url.origin === appOrigin) {
if (typeof input === "string" || input instanceof URL) {
input = url.toString();
} else {
input = new Request(url.toString(), input);
}
return originalFetch.call(window, input, {
...init,
mode: "cors",
});
}
if (url.origin === window.location.origin) {
const newUrl = new URL(baseUrl);
newUrl.pathname = url.pathname;
newUrl.search = url.search;
newUrl.hash = url.hash;
url = newUrl;
if (typeof input === "string" || input instanceof URL) {
input = url.toString();
} else {
input = new Request(url.toString(), input);
}
return originalFetch.call(window, input, {
...init,
mode: "cors",
});
}
return originalFetch.call(window, input, init);
};
}
}).toString() +
")()"}
</script>
</>
);
}