diff --git a/src/lib/open-graph.ts b/src/lib/open-graph.ts index a41007488..8008cb10b 100644 --- a/src/lib/open-graph.ts +++ b/src/lib/open-graph.ts @@ -4,10 +4,23 @@ type RoadmapOpenGraphQuery = { }; export function getOpenGraphImageUrl(params: RoadmapOpenGraphQuery) { - return `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/og/${params.group}-${params.resourceId}`; + return `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/og/${params.group}/${params.resourceId}`; } export async function getDefaultOpenGraphImageBuffer() { const defaultImageUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/images/og-img.png`; return fetch(defaultImageUrl).then((response) => response.arrayBuffer()); } + +export async function getResourceOpenGraph( + type: 'roadmap' | 'guide' | 'best-practice', + resourceId: string, +) { + const url = new URL(`${import.meta.env.PUBLIC_API_URL}/v1-open-graph`); + url.searchParams.set('type', type); + url.searchParams.set('resourceId', resourceId); + url.searchParams.set('variant', 'image'); + const response = await fetch(url.toString()); + + return response.text(); +} diff --git a/src/pages/og/[slug].ts b/src/pages/og/[slug].ts deleted file mode 100644 index 47a059b7b..000000000 --- a/src/pages/og/[slug].ts +++ /dev/null @@ -1,82 +0,0 @@ -import type { APIRoute } from 'astro'; -import { getDefaultOpenGraphImageBuffer } from '../../lib/open-graph'; - -export const prerender = false; - -type Params = { - slug: - | `user-${string}` - | `roadmap-${string}` - | `best-practice-${string}` - | `guide-${string}`; -}; - -export const GET: APIRoute = async (context) => { - const { slug } = context.params; - - if ( - !slug.startsWith('user-') && - !slug.startsWith('roadmap-') && - !slug.startsWith('best-practice') && - !slug.startsWith('guide-') - ) { - const buffer = await getDefaultOpenGraphImageBuffer(); - return new Response(buffer, { - headers: { - 'Content-Type': 'image/png', - }, - }); - } - - if (slug.startsWith('user-')) { - const username = slug.replace('user-', ''); - if (!username) { - const buffer = await getDefaultOpenGraphImageBuffer(); - return new Response(buffer, { - headers: { - 'Content-Type': 'image/png', - }, - }); - } - - const response = await fetch( - `${import.meta.env.PUBLIC_API_URL}/v1-profile-open-graph/${username}`, - ); - - const svg = await response.text(); - return new Response(svg, { - headers: { - 'Content-Type': 'image/svg+xml', - }, - }); - } else { - const type = slug.startsWith('roadmap-') - ? 'roadmap' - : slug.startsWith('best-practice-') - ? 'best-practice' - : 'guide'; - const resourceId = slug.replace(`${type}-`, ''); - - if (!resourceId) { - const buffer = await getDefaultOpenGraphImageBuffer(); - return new Response(buffer, { - headers: { - 'Content-Type': 'image/png', - }, - }); - } - - const url = new URL(`${import.meta.env.PUBLIC_API_URL}/v1-open-graph`); - url.searchParams.set('type', type); - url.searchParams.set('resourceId', resourceId); - url.searchParams.set('variant', 'image'); - const response = await fetch(url.toString()); - - const svg = await response.text(); - return new Response(svg, { - headers: { - 'Content-Type': 'image/svg+xml', - }, - }); - } -}; diff --git a/src/pages/og/best-practice/[slug].ts b/src/pages/og/best-practice/[slug].ts new file mode 100644 index 000000000..794f96d40 --- /dev/null +++ b/src/pages/og/best-practice/[slug].ts @@ -0,0 +1,31 @@ +import type { APIRoute } from 'astro'; +import { + getDefaultOpenGraphImageBuffer, + getResourceOpenGraph, +} from '../../../lib/open-graph'; + +export const prerender = false; + +type Params = { + slug: string; +}; + +export const GET: APIRoute = async (context) => { + const { slug } = context.params; + + if (!slug) { + const buffer = await getDefaultOpenGraphImageBuffer(); + return new Response(buffer, { + headers: { + 'Content-Type': 'image/png', + }, + }); + } + + const svg = await getResourceOpenGraph('best-practice', slug); + return new Response(svg, { + headers: { + 'Content-Type': 'image/svg+xml', + }, + }); +}; diff --git a/src/pages/og/guide/[slug].ts b/src/pages/og/guide/[slug].ts new file mode 100644 index 000000000..0b3737340 --- /dev/null +++ b/src/pages/og/guide/[slug].ts @@ -0,0 +1,31 @@ +import type { APIRoute } from 'astro'; +import { + getDefaultOpenGraphImageBuffer, + getResourceOpenGraph, +} from '../../../lib/open-graph'; + +export const prerender = false; + +type Params = { + slug: string; +}; + +export const GET: APIRoute = async (context) => { + const { slug } = context.params; + + if (!slug) { + const buffer = await getDefaultOpenGraphImageBuffer(); + return new Response(buffer, { + headers: { + 'Content-Type': 'image/png', + }, + }); + } + + const svg = await getResourceOpenGraph('guide', slug); + return new Response(svg, { + headers: { + 'Content-Type': 'image/svg+xml', + }, + }); +}; diff --git a/src/pages/og/roadmap/[slug].ts b/src/pages/og/roadmap/[slug].ts new file mode 100644 index 000000000..1bf9afc45 --- /dev/null +++ b/src/pages/og/roadmap/[slug].ts @@ -0,0 +1,31 @@ +import type { APIRoute } from 'astro'; +import { + getDefaultOpenGraphImageBuffer, + getResourceOpenGraph, +} from '../../../lib/open-graph'; + +export const prerender = false; + +type Params = { + slug: string; +}; + +export const GET: APIRoute = async (context) => { + const { slug } = context.params; + + if (!slug) { + const buffer = await getDefaultOpenGraphImageBuffer(); + return new Response(buffer, { + headers: { + 'Content-Type': 'image/png', + }, + }); + } + + const svg = await getResourceOpenGraph('roadmap', slug); + return new Response(svg, { + headers: { + 'Content-Type': 'image/svg+xml', + }, + }); +}; diff --git a/src/pages/og/user/[username].ts b/src/pages/og/user/[username].ts new file mode 100644 index 000000000..67f52472e --- /dev/null +++ b/src/pages/og/user/[username].ts @@ -0,0 +1,32 @@ +import type { APIRoute } from 'astro'; +import { getDefaultOpenGraphImageBuffer } from '../../../lib/open-graph'; + +export const prerender = false; + +type Params = { + username: string; +}; + +export const GET: APIRoute = async (context) => { + const { username } = context.params; + + if (!username || !/^[a-zA-Z0-9]*?[a-zA-Z]+?[a-zA-Z0-9]*?$/.test(username)) { + const buffer = await getDefaultOpenGraphImageBuffer(); + return new Response(buffer, { + headers: { + 'Content-Type': 'image/png', + }, + }); + } + + const response = await fetch( + `${import.meta.env.PUBLIC_API_URL}/v1-profile-open-graph/${username}`, + ); + + const svg = await response.text(); + return new Response(svg, { + headers: { + 'Content-Type': 'image/svg+xml', + }, + }); +}; diff --git a/src/pages/u/[username].astro b/src/pages/u/[username].astro index 1b414b715..2b8e0dbb1 100644 --- a/src/pages/u/[username].astro +++ b/src/pages/u/[username].astro @@ -24,7 +24,7 @@ if (error || !userDetails) { } const origin = Astro.url.origin; -const ogImage = `${origin}/og/user-${username}`; +const ogImage = `${origin}/og/user/${username}`; ---