ネモラムネ

AstroのOGP画像をSvelteで作る

#JavaScript #Astro #Svelte

2024-06-14

OGP画像っていうのはサイトのリンクを張った時に出る画像のことだよ
こういうやつだね

Astroでブログリニューアル | ネモラムネ
AstroとSvelteでブログを作り直したよ
Astroでブログリニューアル | ネモラムネ favicon nemoramune.com
Astroでブログリニューアル | ネモラムネ

これにはsatoriっていうReactのNodeをsvgにしてくれるライブラリと
shapeっていうsvgをpngに変換してくれるライブラリをつかうよ
だからSvelteを使うときはこんな感じの流れになるよ

  1. Svelteをhtmlに変換
  2. htmlをReactのNodeに変換
  3. satoriでNodeをsvgに変換
  4. shapeでsvgをpngに変換

まずはライブラリをインストールするよ

npm i -D satori satori-html shape

つぎはSvelteのコンポーネントを作るよ
例としてすごく簡単なものにするね

<script>
	export let title
</script>

<h1 style="width: 100%; height: 100%; margin: 0; background-color: cyan;">
	{title}
</h1>

作ったSvelteのコンポーネントをpngにするよ
fontは好きなフォントを入れてね

import satori from 'satori'
import { html as toReactNode } from 'satori-html'
import sharp from 'sharp'

const getOgpImage = async (title: string) => {
	const html = OGPImage.render({ title }).html
	const reactNode = toReactNode(html)
	const fontUrl = '好きなフォントのURL'
	const fontDataResponse = await fetch(fontUrl)
  const fontData = await fontDataResponse.arrayBuffer()

	const svg = await satori(reactNode, {
		width: 1200,
		height: 630,
		fonts: [
			{
				name: '好きなフォント',
				data: fontData
			}
		]
	})

	return await sharp(Buffer.from(svg)).png().toBuffer()
}

そしたら、OGP画像のエンドポイントを追加するよ。
僕はブログのURLの末尾にogp.pngを付けるようにしたいから
pages/blog/[...slug]/ogp.png.tsにTSファイルを作ってるよ

export async function getStaticPaths() {
	const contents = await getCollection('blog')
	return contents.map((post) => ({
		params: { slug: post.slug },
		props: { title: post.data.title }
	}))
}

export const GET: APIRoute = async ({ props }) => {
	const title = props?.title
	if (!title) return new Response()
	const image = await getOgpImage(title)
	return new Response(image)
}

これで完成!
こういう画像ができるよ~
ブログの記事のURLの末尾にogp.pngを追加すれば見れるよ
あとはogpとして表示できるように適当にmetaデータに指定してあげてね