11import type { APIRoute } from 'astro'
22import { getCollection } from 'astro:content'
33import { generateOpenGraphImage } from 'astro-og-canvas'
4- import { access , mkdir , writeFile } from 'node:fs/promises'
5- import { tmpdir } from 'node:os'
6- import { join } from 'node:path'
4+ import { fileURLToPath } from 'node:url'
75import { buildApiErrorResponse , handleApiFunctionError } from '@pages/api/_utils/errors'
86import { createApiFunctionContext } from '@pages/api/_utils/requestContext'
97
108export const prerender = false
119
1210const ROUTE = '/api/social-card'
13- const PUBLIC_AVATAR_PATH = '/assets/images/kevin-brown.webp'
14- const CACHED_AVATAR_DIRECTORY = join ( tmpdir ( ) , 'webstackbuilders-social-cards' )
15- const CACHED_AVATAR_PATH = join ( CACHED_AVATAR_DIRECTORY , 'kevin-brown.webp' )
11+ const AVATAR_FILE_PATH = fileURLToPath (
12+ new URL ( '../../../assets/images/avatars/kevin-brown.webp' , import . meta . url )
13+ )
1614const DEFAULT_TITLE = 'Platform Engineering by Kevin Brown'
1715const DEFAULT_DESCRIPTION =
1816 'Platform engineer helping teams harden delivery, modernize cloud platforms, and improve developer experience.'
@@ -61,29 +59,6 @@ const gradientPalette: Record<PaletteKey, [number, number, number][]> = {
6159 ] ,
6260}
6361
64- const getAvatarFilePath = async ( requestUrl : string ) : Promise < string > => {
65- try {
66- await access ( CACHED_AVATAR_PATH )
67- return CACHED_AVATAR_PATH
68- } catch {
69- // Cache miss; fetch from the public asset URL and persist locally for astro-og-canvas.
70- }
71-
72- const avatarUrl = new URL ( PUBLIC_AVATAR_PATH , requestUrl )
73- const response = await fetch ( avatarUrl )
74-
75- if ( ! response . ok ) {
76- throw new Error ( `Unable to fetch Kevin Brown avatar from ${ avatarUrl . toString ( ) } ` )
77- }
78-
79- const avatarBuffer = Buffer . from ( await response . arrayBuffer ( ) )
80-
81- await mkdir ( CACHED_AVATAR_DIRECTORY , { recursive : true } )
82- await writeFile ( CACHED_AVATAR_PATH , avatarBuffer )
83-
84- return CACHED_AVATAR_PATH
85- }
86-
8762/** Normalize slug parameters to a consistent format */
8863const normalizeSlug = ( value : string | null ) : string => {
8964 if ( ! value ) return 'home'
@@ -147,7 +122,6 @@ export const GET: APIRoute = async ({ request, clientAddress, cookies }) => {
147122 const slug = normalizeSlug ( url . searchParams . get ( 'slug' ) )
148123 const titleOverride = url . searchParams . get ( 'title' )
149124 const descriptionOverride = url . searchParams . get ( 'description' )
150- const avatarPath = await getAvatarFilePath ( request . url )
151125
152126 const contentIndex = await buildContentIndex ( )
153127 const matchedEntry = contentIndex [ slug ]
@@ -167,7 +141,7 @@ export const GET: APIRoute = async ({ request, clientAddress, cookies }) => {
167141 bgGradient : gradientPalette [ palette ] ,
168142 padding : 80 ,
169143 logo : {
170- path : avatarPath ,
144+ path : AVATAR_FILE_PATH ,
171145 size : [ 140 , 140 ] ,
172146 } ,
173147 font : {
0 commit comments