your personal website on atproto - mirror blento.app
26
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #280 from flo-bit/fix/og-images

Fix/og images

authored by

Florian and committed by
GitHub
ef928d8b a2eaa5e5

+51 -5
+4
src/lib/helper.ts
··· 295 295 } 296 296 297 297 await Promise.all(promises); 298 + 299 + // Invalidate cached OG image so the next scrape regenerates it. 300 + // Fire-and-forget; server checks auth against the signed-cookie session. 301 + fetch(`/${data.did}/og-new.png`, { method: 'DELETE' }).catch(() => {}); 298 302 } 299 303 300 304 export function createEmptyCard(page: string) {
+10 -1
src/lib/website/EditableWebsite.svelte
··· 21 21 import { tick, type Component } from 'svelte'; 22 22 import type { CardDefinition, CreationModalComponentProps } from '../cards/types'; 23 23 import { dev } from '$app/environment'; 24 + import { page } from '$app/state'; 24 25 import { setIsCoarse, setIsMobile, setSelectedCardId, setSelectCard } from './context'; 25 26 import BaseEditingCard from '../cards/_base/BaseCard/BaseEditingCard.svelte'; 26 27 import Context from './Context.svelte'; ··· 55 56 56 57 // Check if floating login button will be visible (to hide MadeWithBlento) 57 58 const showLoginOnEditPage = $derived(!user.isLoggedIn); 59 + 60 + const ogImageUrl = $derived.by(() => { 61 + const origin = page.url.origin; 62 + if (page.data.customDomain) return `${origin}/og-new.png`; 63 + const handle = data.profile?.handle; 64 + const actor = handle && handle !== 'handle.invalid' ? handle : data.did; 65 + return `${origin}/${actor}/og-new.png`; 66 + }); 58 67 59 68 // Snapshot the original cards so savePage can detect deletions. 60 69 const originalCards: Item[] = structuredClone(data.cards); ··· 516 525 <Head 517 526 favicon={getImage(data.publication, data.did, 'icon') || data.profile.avatar} 518 527 title={getName(data)} 519 - image={'/' + data.handle + '/og-new.png'} 528 + image={ogImageUrl} 520 529 accentColor={data.publication?.preferences?.accentColor} 521 530 baseColor={data.publication?.preferences?.baseColor} 522 531 />
+9 -1
src/lib/website/Website.svelte
··· 47 47 // svelte-ignore state_referenced_locally 48 48 setHandleContext(data.handle as Handle); 49 49 50 + const ogImageUrl = $derived.by(() => { 51 + const origin = page.url.origin; 52 + if (page.data.customDomain) return `${origin}/og-new.png`; 53 + const handle = data.profile?.handle; 54 + const actor = handle && handle !== 'handle.invalid' ? handle : data.did; 55 + return `${origin}/${actor}/og-new.png`; 56 + }); 57 + 50 58 let maxHeight = $derived( 51 59 data.cards.reduce( 52 60 (max, item) => Math.max(max, isMobile ? item.mobileY + item.mobileH : item.y + item.h), ··· 60 68 <Head 61 69 favicon={getImage(data.publication, data.did, 'icon') || data.profile.avatar} 62 70 title={getName(data)} 63 - image={'/' + data.handle + '/og-new.png'} 71 + image={ogImageUrl} 64 72 description={getDescription(data)} 65 73 accentColor={data.publication?.preferences?.accentColor} 66 74 baseColor={data.publication?.preferences?.baseColor}
+28 -3
src/routes/[[actor=actor]]/og-new.png/+server.ts
··· 1 1 import { env } from '$env/dynamic/private'; 2 2 import { env as publicEnv } from '$env/dynamic/public'; 3 - import { error } from '@sveltejs/kit'; 3 + import { error, json } from '@sveltejs/kit'; 4 4 import { getActor } from '$lib/actor'; 5 5 import { createCache } from '$lib/cache'; 6 6 ··· 30 30 }); 31 31 } 32 32 33 - const handle = params.actor ?? publicEnv.PUBLIC_HANDLE; 34 - const siteUrl = `${publicEnv.PUBLIC_DOMAIN}/${handle}`; 33 + const siteUrl = `${publicEnv.PUBLIC_DOMAIN}/${actor}`; 35 34 36 35 const accountId = env.CLOUDFLARE_ACCOUNT_ID; 37 36 const apiToken = env.CLOUDFLARE_API_TOKEN; ··· 86 85 } 87 86 }); 88 87 } 88 + 89 + export async function DELETE({ params, platform, request, locals }) { 90 + if (!locals.did) { 91 + throw error(401, 'Not authenticated'); 92 + } 93 + 94 + const actor = await getActor({ 95 + request, 96 + paramActor: params.actor, 97 + platform, 98 + blockBoth: false 99 + }); 100 + 101 + if (!actor) { 102 + throw error(404, 'Page not found'); 103 + } 104 + 105 + if (actor !== locals.did) { 106 + throw error(403, "Cannot invalidate another user's OG image"); 107 + } 108 + 109 + const cache = createCache(platform); 110 + await cache?.delete('og', actor); 111 + 112 + return json({ success: true }); 113 + }