From 7de99e32f690fc97e74b04ee1c6c35297d065bfe Mon Sep 17 00:00:00 2001 From: royendo <67675319+royendo@users.noreply.github.com> Date: Fri, 13 Mar 2026 12:56:11 -0400 Subject: [PATCH 1/2] trying --- next.config.ts | 2 +- src/app/components/IframeFetcher.tsx | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/next.config.ts b/next.config.ts index e9ffa30..65c102b 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + output: "export", }; export default nextConfig; diff --git a/src/app/components/IframeFetcher.tsx b/src/app/components/IframeFetcher.tsx index 0b755a8..01b28fa 100644 --- a/src/app/components/IframeFetcher.tsx +++ b/src/app/components/IframeFetcher.tsx @@ -13,12 +13,21 @@ interface IframeFetcherProps { }; } +const iframeCache = new Map(); + const IframeFetcher = ({ org, project, body }: IframeFetcherProps) => { const [iframeUrl, setIframeUrl] = useState(null); const [error, setError] = useState(null); const bodyString = useMemo(() => JSON.stringify(body), [body]); + const cacheKey = `${org}:${project}:${bodyString}`; useEffect(() => { + const cached = iframeCache.get(cacheKey); + if (cached) { + setIframeUrl(cached); + return; + } + const fetchUrl = async () => { try { const res = await fetch('/api/get-iframe', { @@ -29,6 +38,7 @@ const IframeFetcher = ({ org, project, body }: IframeFetcherProps) => { const data = await res.json(); if (!res.ok) throw new Error(data.error || 'Failed to fetch iframe'); + iframeCache.set(cacheKey, data.iframeUrl); setIframeUrl(data.iframeUrl); } catch (err) { if (err instanceof Error) { @@ -41,7 +51,7 @@ const IframeFetcher = ({ org, project, body }: IframeFetcherProps) => { }; fetchUrl(); - }, [org, project, bodyString]); + }, [org, project, bodyString, cacheKey]); if (error) return

Error loading iframe: {error}

; if (!iframeUrl) return

Loading...

; From db9178ed7afa025035637e376f58e32f2a8ad9fd Mon Sep 17 00:00:00 2001 From: royendo <67675319+royendo@users.noreply.github.com> Date: Fri, 13 Mar 2026 13:14:50 -0400 Subject: [PATCH 2/2] neltify function --- netlify.toml | 6 ++++++ netlify/functions/get-iframe.ts | 32 ++++++++++++++++++++++++++++ src/app/components/IframeFetcher.tsx | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 netlify.toml create mode 100644 netlify/functions/get-iframe.ts diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 0000000..9847c21 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,6 @@ +[build] + command = "npm run build" + publish = "out" + +[functions] + directory = "netlify/functions" diff --git a/netlify/functions/get-iframe.ts b/netlify/functions/get-iframe.ts new file mode 100644 index 0000000..3282d90 --- /dev/null +++ b/netlify/functions/get-iframe.ts @@ -0,0 +1,32 @@ +export default async (req: Request) => { + if (req.method !== 'POST') { + return new Response('Method not allowed', { status: 405 }); + } + + const { org, project, body } = await req.json(); + + const rillServiceToken = process.env.RILL_SERVICE_TOKEN!; + const url = `https://admin.rilldata.com/v1/organizations/${org}/projects/${project}/iframe`; + + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${rillServiceToken}`, + }, + body: JSON.stringify(body), + }); + + const data = await response.json(); + + if (!response.ok) { + return new Response(JSON.stringify({ error: data.message || 'Failed to fetch iframe URL' }), { + status: 500, + headers: { 'Content-Type': 'application/json' }, + }); + } + + return new Response(JSON.stringify({ iframeUrl: data.iframeSrc }), { + headers: { 'Content-Type': 'application/json' }, + }); +}; diff --git a/src/app/components/IframeFetcher.tsx b/src/app/components/IframeFetcher.tsx index 01b28fa..b090535 100644 --- a/src/app/components/IframeFetcher.tsx +++ b/src/app/components/IframeFetcher.tsx @@ -30,7 +30,7 @@ const IframeFetcher = ({ org, project, body }: IframeFetcherProps) => { const fetchUrl = async () => { try { - const res = await fetch('/api/get-iframe', { + const res = await fetch('/.netlify/functions/get-iframe', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ org, project, body: JSON.parse(bodyString) }),