The share/[id] layout is a server component that imported FAVICON_SERVICE_URL from icons.tsx, pulling in the entire React icon registry and triggering createContext on the server. Moved the constant to its own favicon.ts module.
74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import { FAVICON_SERVICE_URL } from '@/lib/utils/favicon'
|
|
|
|
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8082'
|
|
|
|
interface SharePageParams {
|
|
params: Promise<{ id: string }>
|
|
}
|
|
|
|
export async function generateMetadata({ params }: SharePageParams): Promise<Metadata> {
|
|
const { id } = await params
|
|
const fallback: Metadata = {
|
|
title: 'Public Dashboard | Pulse',
|
|
description: 'Privacy-first web analytics — view this site\'s public stats.',
|
|
openGraph: {
|
|
title: 'Public Dashboard | Pulse',
|
|
description: 'Privacy-first web analytics — view this site\'s public stats.',
|
|
siteName: 'Pulse by Ciphera',
|
|
type: 'website',
|
|
},
|
|
twitter: {
|
|
card: 'summary',
|
|
title: 'Public Dashboard | Pulse',
|
|
description: 'Privacy-first web analytics — view this site\'s public stats.',
|
|
},
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(`${API_URL}/public/sites/${id}/dashboard?limit=1`, {
|
|
next: { revalidate: 3600 },
|
|
})
|
|
if (!res.ok) return fallback
|
|
|
|
const data = await res.json()
|
|
const domain = data?.site?.domain
|
|
if (!domain) return fallback
|
|
|
|
const title = `${domain} analytics | Pulse`
|
|
const description = `Live, privacy-first analytics for ${domain} — powered by Pulse.`
|
|
|
|
return {
|
|
title,
|
|
description,
|
|
openGraph: {
|
|
title,
|
|
description,
|
|
siteName: 'Pulse by Ciphera',
|
|
type: 'website',
|
|
images: [{
|
|
url: `${FAVICON_SERVICE_URL}?domain=${domain}&sz=128`,
|
|
width: 128,
|
|
height: 128,
|
|
alt: `${domain} favicon`,
|
|
}],
|
|
},
|
|
twitter: {
|
|
card: 'summary',
|
|
title,
|
|
description,
|
|
},
|
|
}
|
|
} catch {
|
|
return fallback
|
|
}
|
|
}
|
|
|
|
export default function ShareLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
return children
|
|
}
|