import { Card } from '@sanity/ui' import { height, OpenGraphImage, width } from 'components/OpenGraphImage' import { createIntlSegmenterPolyfill } from 'intl-segmenter-polyfill' import type { Settings } from 'lib/sanity.queries' import satori, { type SatoriOptions } from 'satori' import styled from 'styled-components' import useSWR from 'swr/immutable' async function init(): Promise { if (!globalThis?.Intl?.Segmenter) { console.debug('Polyfilling Intl.Segmenter') //@ts-expect-error globalThis.Intl = globalThis.Intl || {} //@ts-expect-error globalThis.Intl.Segmenter = await createIntlSegmenterPolyfill( fetch(new URL('public/break_iterator.wasm', import.meta.url)) ) } const fontData = await fetch( new URL('public/fonts/Inter-Bold.woff', import.meta.url) ).then((res) => res.arrayBuffer()) return [{ name: 'Inter', data: fontData, style: 'normal', weight: 700 }] } // preload fonts and polyfill const fontsPromise = init() const OpenGraphSvg = styled(Card).attrs({ radius: 3, shadow: 1, overflow: 'hidden', })` display: flex; align-items: center; justify-content: center; svg { display: block; object-fit: cover; aspect-ratio: ${width} / ${height}; object-position: center; height: 100%; width: 100%; } ` export default function OpenGraphPreview(props: Settings['ogImage']) { // we wrap the segmenter setup and font loading in SWR to enable caching const { data: fonts } = useSWR('OpenGraphPreview.init', () => fontsPromise, { suspense: true, }) // Also handle the satori render call in SWR to enable caching and only re-render when the title changes or fonts hot reload const { data: __html } = useSWR( [props.title, fonts satisfies SatoriOptions['fonts']], ([title, fonts]) => { return satori(, { width, height, fonts, }) }, { suspense: true } ) return }