From f234013a92fb44e347671a9211ba403e383b740f Mon Sep 17 00:00:00 2001 From: Lalith Date: Thu, 30 Apr 2026 16:02:25 -0500 Subject: [PATCH 01/26] create embed URL with iframe-safe layout and CSP --- packages/app/src/app/embed/scatter/page.tsx | 13 +++ packages/app/src/app/layout.tsx | 7 +- .../embed/embed-scatter-client-page.tsx | 16 ++++ .../components/embed/embed-scatter-view.tsx | 44 ++++++++++ .../components/ui/chart-display-helpers.tsx | 13 ++- packages/app/src/lib/url-state.test.ts | 21 +++++ packages/app/src/lib/url-state.ts | 81 +++++++++++++++++++ packages/app/src/middleware.ts | 24 ++++++ 8 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 packages/app/src/app/embed/scatter/page.tsx create mode 100644 packages/app/src/components/embed/embed-scatter-client-page.tsx create mode 100644 packages/app/src/components/embed/embed-scatter-view.tsx create mode 100644 packages/app/src/middleware.ts diff --git a/packages/app/src/app/embed/scatter/page.tsx b/packages/app/src/app/embed/scatter/page.tsx new file mode 100644 index 00000000..5acbb137 --- /dev/null +++ b/packages/app/src/app/embed/scatter/page.tsx @@ -0,0 +1,13 @@ +import type { Metadata } from 'next'; + +import { EmbedScatterClientPage } from '@/components/embed/embed-scatter-client-page'; + +export const metadata: Metadata = { + title: 'InferenceX Embed Scatter', + description: 'Embeddable InferenceX scatter chart.', + robots: { index: false, follow: false }, +}; + +export default function EmbedScatterPage() { + return ; +} diff --git a/packages/app/src/app/layout.tsx b/packages/app/src/app/layout.tsx index 22bda276..c6af1d5a 100644 --- a/packages/app/src/app/layout.tsx +++ b/packages/app/src/app/layout.tsx @@ -4,6 +4,7 @@ import './globals.css'; import { Analytics } from '@vercel/analytics/next'; import { SpeedInsights } from '@vercel/speed-insights/next'; import type { Metadata } from 'next'; +import { headers } from 'next/headers'; import { DM_Sans } from 'next/font/google'; import localFont from 'next/font/local'; @@ -167,6 +168,8 @@ export default async function RootLayout({ }: Readonly<{ children: React.ReactNode; }>) { + const requestHeaders = await headers(); + const isEmbedRoute = requestHeaders.get('x-inferencex-embed') === '1'; const starCount = await fetchStarCount(); return ( @@ -189,9 +192,9 @@ export default async function RootLayout({ disableTransitionOnChange > -
+ {!isEmbedRoute &&
}
{children}
-