Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dynamic opengraph image via Cloudflare Pages Functions #407

Merged
merged 4 commits into from
Mar 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions functions/api/og.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { ImageResponse } from '@cloudflare/pages-plugin-vercel-og/api'

export function onRequest({ request }: { request: Request }) {
const params = new URL(request.url).searchParams
const title = params.get('title')

return new ImageResponse(
(
<div
style={{
background: '#F6F6F6',
width: '100%',
height: '100%',
display: 'flex',
padding: '40px',
}}
>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '24px',
width: '100%',
backgroundColor: 'white',
justifyContent: 'center',
padding: '0 48px',
textAlign: 'center',
borderRadius: '2rem',
}}
>
{/* Logo */}
<div style={{ display: 'flex' }}>
<svg
width="240"
height="76"
viewBox="0 0 240 76"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_1993_35)">
<path
d="M216.095 66.3193C203.569 66.3193 193.11 61.3505 191.721 49.4814C191.678 49.1141 191.943 48.7817 192.309 48.7348L205.161 47.0894C205.564 47.0379 205.921 47.3464 205.957 47.7509C206.472 53.6631 210.654 56.3343 216.417 56.3343C222.527 56.3343 225.635 54.0796 225.635 50.107C225.635 46.564 221.562 45.2756 213.093 43.2357C202.802 40.7662 193.369 37.5452 193.369 26.4865C193.369 14.6763 203.767 10.0596 215.345 10.0596C226.925 10.0596 236.85 13.8907 238.523 25.6202C238.574 25.9823 238.325 26.32 237.965 26.3814L225.539 28.5038C225.133 28.5731 224.76 28.2704 224.717 27.8606C224.142 22.3907 220.683 19.9373 215.559 19.9373C211.164 19.9373 207.519 21.5477 207.519 25.3056C207.519 28.956 211.378 30.2444 218.561 31.8548C228.101 34.0021 240 36.5789 240 49.3555C240 62.2394 228.637 66.3193 216.095 66.3193Z"
fill="#0080BC"
/>
<path
d="M183.327 15.1712C187.615 19.4659 188.151 25.2636 188.151 32.2424V65.1609C188.151 65.5415 187.843 65.85 187.463 65.85H173.725C173.345 65.85 173.037 65.5415 173.037 65.1609V33.5308C173.037 28.592 172.608 26.0152 170.249 23.7605C168.32 21.9353 166.497 21.6132 163.281 21.6132C158.672 21.6132 153.312 24.7268 153.312 35.7855V65.1609C153.312 65.5415 153.004 65.85 152.624 65.85H138.993C138.613 65.85 138.305 65.5415 138.305 65.1609V12.1025C138.305 11.722 138.613 11.4134 138.993 11.4134H152.517C152.897 11.4134 153.205 11.722 153.205 12.1025V17.9452C153.205 18.2752 153.694 18.3796 153.848 18.0875C156.864 12.3488 162.597 10.125 169.07 10.125C175.931 10.125 179.897 11.7356 183.327 15.1712Z"
fill="#0080BC"
/>
<path
d="M126.429 16.9636C131.633 22.2644 134.255 30.3209 134.476 40.5236C134.484 40.8986 134.187 41.2096 133.813 41.2214L95.9679 42.4196C95.5855 42.4317 95.2847 42.7567 95.3111 43.1396C95.8983 51.6836 100.305 55.9245 108.131 55.6768C114.734 55.4677 118.067 52.4733 119.105 47.2382C119.173 46.8916 119.482 46.6401 119.834 46.66L133.015 47.4054C133.44 47.4295 133.741 47.8323 133.637 48.2452C130.707 59.8437 121.983 65.8728 108.466 66.3007C100.109 66.5653 93.3815 64.0928 88.7423 59.8355C83.4407 54.9546 80.6455 47.9534 80.3607 38.9392C80.0903 30.3542 82.2167 22.9824 87.3079 17.7725C91.8767 13.0088 98.2271 10.337 106.585 10.0725C115.049 9.80445 121.777 12.2769 126.429 16.9636ZM106.913 20.4817C102.52 20.6209 99.4535 22.0069 97.5023 24.7542C96.1919 26.5572 95.4279 28.7886 95.1287 31.3698C95.0815 31.7778 95.4127 32.1249 95.8223 32.1119L118.19 31.4037C118.596 31.3909 118.903 31.0299 118.84 30.6281C118.37 27.6449 117.423 25.1489 115.583 23.3225C113.479 21.2406 110.77 20.3597 106.913 20.4817Z"
fill="#0080BC"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M33.9787 1.63889C33.7035 1.22039 34.2094 0.730331 34.6199 1.01769L51.806 13.0472C62.6378 20.629 67.6252 34.166 64.191 46.9231C63.919 47.9338 63.6271 48.8184 63.353 49.5596C63.183 50.0191 62.5072 49.9199 62.4731 49.4312C62.1834 45.2774 59.1924 40.5285 57.0215 37.0818C56.634 36.4664 56.2726 35.8927 55.9574 35.3711C53.8474 31.8806 38.5735 8.62753 33.9787 1.63889ZM11.2229 35.4725L31.794 1.62411C32.0329 1.2312 31.603 0.7729 31.1951 0.985612C27.5989 2.86048 17.8954 8.2851 10.2773 15.8935C1.92865 24.2314 8.6756 33.3796 10.4866 35.5298C10.6867 35.7674 11.0615 35.7379 11.2229 35.4725ZM31.2855 74.7075C31.5607 75.1259 31.0548 75.616 30.6443 75.3287L13.4582 63.2991C2.62651 55.7174 -2.36094 42.1803 1.07322 29.4232C1.34525 28.4126 1.63713 27.5279 1.91129 26.7867C2.08128 26.3272 2.75705 26.4264 2.79113 26.9151C3.08087 31.0689 6.07185 35.8178 8.24272 39.2646C8.63024 39.8798 8.9916 40.4537 9.30688 40.9752C11.4168 44.4658 26.6907 67.7188 31.2855 74.7075ZM33.4718 74.7187L54.043 40.8702C54.2044 40.6049 54.5792 40.5753 54.7794 40.8129C56.5903 42.9631 63.3373 52.1113 54.9886 60.4492C47.3705 68.0576 37.667 73.4822 34.0709 75.3571C33.6629 75.5699 33.233 75.1115 33.4718 74.7187Z"
fill="#0080BC"
/>
</g>
<defs>
<clipPath id="clip0_1993_35">
<rect
width="240"
height="75.2"
fill="white"
transform="translate(0 0.400391)"
/>
</clipPath>
</defs>
</svg>
</div>

{/* Title */}
<h1
style={{
fontSize: 64,
margin: 0,
lineHeight: 1.2,
whiteSpace: 'normal',
}}
>
{title}
</h1>

<div
style={{
position: 'absolute',
bottom: '16px',
left: '16px',
background: '#EEF5FF',
color: '#3889FF',
padding: '6px 16px',
borderRadius: '30px',
lineHeight: '30px',
fontSize: '30px',
fontWeight: 700,
}}
>
Docs
</div>
</div>
</div>
),
{
width: 1200,
height: 630,
}
)
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"preview": "vocs preview"
},
"dependencies": {
"@cloudflare/pages-plugin-vercel-og": "^0.1.2",
"@tanstack/react-query": "^5.64.1",
"clsx": "^2.1.1",
"gray-matter": "^4.0.3",
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion vocs.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ try {

// Cloudflare doesn't expose NODE_ENV, so checking the source branch is our easiest workaround
const isProd = process.env.CF_PAGES_BRANCH === 'master'
const baseUrl = isProd ? 'https://docs.ens.domains' : process.env.CF_PAGES_URL

export default defineConfig({
title: 'ENS Documentation',
titleTemplate: '%s | ENS Docs',
rootDir: 'src',
iconUrl: '/img/icon.svg',
logoUrl: '/img/logo-mark.svg',
baseUrl: isProd ? 'https://docs.ens.domains' : process.env.CF_PAGES_URL, // Not required, so ok if it's undefined
baseUrl,
ogImageUrl: baseUrl ? `${baseUrl}/api/og?title=%title` : undefined,
editLink: {
pattern: 'https://github.com/ensdomains/docs/edit/master/src/pages/:path',
text: 'Edit on Github',
Expand Down