Fixing up the og image generation.

This commit is contained in:
Bradley Shellnut 2023-09-13 22:52:34 -07:00
parent 9f69946504
commit eac61fffe3
3 changed files with 97 additions and 37 deletions

View file

@ -1,14 +1,65 @@
<script lang="ts"> <script lang="ts">
import * as Card from "$lib/components/ui/card";
export let title: string; export let title: string;
export let image: string;
export let description: string;
</script> </script>
<Card.Root class="w-[350px]"> <div class="social-card">
<Card.Header> <div class="social-card-header">
<Card.Title class="flex place-items-center gap-1"><div class="w-8 h-8"><img src="/images/bored-game.png" alt="Bored Game" /></div>{title}</Card.Title> <div class="social-card-title">
</Card.Header> <div class="social-card-image">
<Card.Content> <img src={image || '/images/bored-game.png'} alt="Bored Game" />
<slot /> </div>
</Card.Content> <p>{title}</p>
</Card.Root> </div>
</div>
<div class="social-card-content">
<p>{description}</p>
</div>
</div>
<style>
@font-face {
font-family: 'Noto Sans';
src: url('/src/lib/NotoSans-Regular.ttf');
}
.social-card {
display: flex;
flex-direction: column;
border-radius: 0.5rem;
border-width: 1px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
width: 350px;
}
.social-card-header {
display: flex;
padding: 1.5rem;
margin-top: 0.375rem;
flex-direction: column;
}
.social-card-title {
display: flex;
gap: 0.25rem;
place-items: center;
font-size: 1.125rem;
line-height: 1.75rem;
font-weight: 600;
letter-spacing: -0.025em;
line-height: 1;
}
.social-card-image {
display: flex;
width: 2rem;
height: 2rem;
}
.social-card-content {
display: flex;
padding: 1.5rem;
padding-top: 0;
}
</style>

View file

@ -14,7 +14,9 @@ export const load = async ({ fetch, url }) => {
description: 'Bored Game, keep track of your games', description: 'Bored Game, keep track of your games',
images: [ images: [
{ {
url: `${new URL(url.pathname, url.origin).href}og?title=Home | Bored Game`, url: `${
new URL(url.pathname, url.origin).href
}og?title=Home | Bored Game&description=Bored Game, keep track of your games`,
width: 1200, width: 1200,
height: 630 height: 630
} }

View file

@ -9,33 +9,40 @@ const height = 630;
const width = 1200; const width = 1200;
export const GET: RequestHandler = async ({ url }) => { export const GET: RequestHandler = async ({ url }) => {
const title = url.searchParams.get('title') ?? undefined; try {
const result = SocialImageCard.render({ title }); const ogImage = `${new URL(url.origin).href}images/bored-game.png`;
const element = toReactNode(`${result.html}<style>${result.css.code}</style>`); const title = url.searchParams.get('title') ?? undefined;
const svg = await satori(element, { const description = url.searchParams.get('description') ?? '';
fonts: [ const result = SocialImageCard.render({ title, image: ogImage, description });
{ console.log('result', result);
name: 'Noto Sans', const element = toReactNode(`${result.html}<style>${result.css.code}</style>`);
data: Buffer.from(NotoSans), const svg = await satori(element, {
style: 'normal' fonts: [
{
name: 'Noto Sans',
data: Buffer.from(NotoSans),
style: 'normal'
}
],
height,
width
});
const resvg = new Resvg(svg, {
fitTo: {
mode: 'width',
value: width
} }
], });
height,
width
});
const resvg = new Resvg(svg, { const image = resvg.render();
fitTo: {
mode: 'width',
value: width
}
});
const image = resvg.render(); return new Response(image.asPng(), {
headers: {
return new Response(image.asPng(), { 'content-type': 'image/png'
headers: { }
'content-type': 'image/png' });
} } catch (e) {
}); console.error(e);
}
}; };