diff --git a/apps/web/playwright/booking-pages.e2e.ts b/apps/web/playwright/booking-pages.e2e.ts index 9cb6baae95..0b0bbf57cf 100644 --- a/apps/web/playwright/booking-pages.e2e.ts +++ b/apps/web/playwright/booking-pages.e2e.ts @@ -55,10 +55,10 @@ test("check SSR and OG - User Event Type", async ({ page, users }) => { expect(canonicalLink).toEqual(`${WEBAPP_URL}/${user.username}/30-min`); // Verify that there is correct URL that would generate the awesome OG image expect(ogImage).toContain( - "/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage?type=meeting&title=30%20min" + "/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage%3Ftype%3Dmeeting%26title%3D30%2Bmin" ); // Verify Organizer Name in the URL - expect(ogImage).toContain("meetingProfileName=Test%20User"); + expect(ogImage).toContain("meetingProfileName%3DTest%2BUser"); }); todo("check SSR and OG - Team Event Type"); diff --git a/apps/web/playwright/organization/booking.e2e.ts b/apps/web/playwright/organization/booking.e2e.ts index c5c0876c7d..c63055eff2 100644 --- a/apps/web/playwright/organization/booking.e2e.ts +++ b/apps/web/playwright/organization/booking.e2e.ts @@ -428,10 +428,10 @@ test.describe("Bookings", () => { expect(canonicalLink).toEqual(`${orgOrigin}${calLink}`); // Verify that there is correct URL that would generate the awesome OG image expect(ogImage).toContain( - "/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage?type=meeting&title=" + "/_next/image?w=1200&q=100&url=%2Fapi%2Fsocial%2Fog%2Fimage%3Ftype%3Dmeeting%26title%3D" ); // Verify Organizer Name in the URL - expect(ogImage).toContain("meetingProfileName=Test%20User"); + expect(ogImage).toContain("meetingProfileName%3DTest%2BUser"); } ); }); diff --git a/apps/web/playwright/settings/upload-avatar.e2e.ts b/apps/web/playwright/settings/upload-avatar.e2e.ts index 9763e901dc..9ead8f6dde 100644 --- a/apps/web/playwright/settings/upload-avatar.e2e.ts +++ b/apps/web/playwright/settings/upload-avatar.e2e.ts @@ -64,9 +64,10 @@ test.describe("User Avatar", async () => { ); // verify objectKey is passed to the OG image // yes, OG image URI encodes at multiple places.. don't want to mess with that. + const searchParam = `meetingImage=${encodeURIComponent(`${CAL_URL}/api/avatar/${objectKey}.png`)}`; await expect(page.locator('meta[property="og:image"]')).toHaveAttribute( "content", - new RegExp(`meetingImage=${encodeURIComponent(`${CAL_URL}/api/avatar/${objectKey}.png`)}`) + new RegExp(encodeURIComponent(searchParam)) ); }); }); diff --git a/packages/lib/OgImages.tsx b/packages/lib/OgImages.tsx index ca4e17791f..e96c9c4bba 100644 --- a/packages/lib/OgImages.tsx +++ b/packages/lib/OgImages.tsx @@ -57,17 +57,22 @@ const makeAbsoluteUrl = (url: string) => (/^https?:\/\//.test(url) ? url : `${CA * 5. Dynamic collective (2 persons) http://localhost:3000/api/social/og/image?type=meeting&title=15min&meetingProfileName=Team%20Pro%20Example,%20Pro%20Example&names=Team%20Pro%20Example&names=Pro%20Example&usernames=teampro&usernames=pro */ export const constructMeetingImage = ({ title, users = [], profile }: MeetingImageProps): string => { - const url = [ - `?type=meeting`, - `&title=${encodeURIComponent(title)}`, - `&meetingProfileName=${encodeURIComponent(profile.name)}`, - profile.image && `&meetingImage=${encodeURIComponent(makeAbsoluteUrl(profile.image))}`, - `${users.map((user) => `&names=${encodeURIComponent(user.name)}`).join("")}`, - `${users.map((user) => `&usernames=${encodeURIComponent(user.username)}`).join("")}`, - // Joining a multiline string for readability. - ].join(""); + const params = new URLSearchParams({ + type: "meeting", + title, + meetingProfileName: profile.name, + }); - return url; + if (profile.image) { + params.set("meetingImage", makeAbsoluteUrl(profile.image)); + } + + users.forEach((user) => { + params.append("names", user.name); + params.append("usernames", user.username); + }); + + return encodeURIComponent(`/api/social/og/image?${params.toString()}`); }; /** @@ -75,26 +80,22 @@ export const constructMeetingImage = ({ title, users = [], profile }: MeetingIma * http://localhost:3000/api/social/og/image?type=app&name=Huddle01&slug=/api/app-store/huddle01video/icon.svg&description=Huddle01%20is%20a%20new%20video%20conferencing%20software%20native%20to%20Web3%20and%20is%20comparable%20to%20a%20decentralized%20version%20of%20Zoom.%20It%20supports%20conversations%20for... */ export const constructAppImage = ({ name, slug, description }: AppImageProps): string => { - const url = [ - `?type=app`, - `&name=${encodeURIComponent(name)}`, - `&slug=${encodeURIComponent(slug)}`, - `&description=${encodeURIComponent(description)}`, - // Joining a multiline string for readability. - ].join(""); - - return url; + const params = new URLSearchParams({ + type: "app", + name, + slug, + description, + }); + return encodeURIComponent(`/api/social/og/image?${params.toString()}`); }; export const constructGenericImage = ({ title, description }: GenericImageProps) => { - const url = [ - `?type=generic`, - `&title=${encodeURIComponent(title)}`, - `&description=${encodeURIComponent(description)}`, - // Joining a multiline string for readability. - ].join(""); - - return url; + const params = new URLSearchParams({ + type: "generic", + title, + description, + }); + return encodeURIComponent(`/api/social/og/image?${params.toString()}`); }; const Wrapper = ({ children, variant = "light", rotateBackground }: WrapperProps) => ( diff --git a/packages/lib/constants.ts b/packages/lib/constants.ts index 43b68b070d..6c154a0a56 100644 --- a/packages/lib/constants.ts +++ b/packages/lib/constants.ts @@ -87,9 +87,7 @@ export const SEO_IMG_DEFAULT = `${CAL_URL}/og-image.png`; // This results in a 80% smaller image 🤯. It is however important that for the query // parameters you pass to the /api/social/og/image endpoint, you wrap them in encodeURIComponent // as well, otherwise the URL won't be valid. -export const SEO_IMG_OGIMG = `${CAL_URL}/_next/image?w=1200&q=100&url=${encodeURIComponent( - `/api/social/og/image` -)}`; +export const SEO_IMG_OGIMG = `${CAL_URL}/_next/image?w=1200&q=100&url=`; export const SEO_IMG_OGIMG_VIDEO = `${CAL_URL}/video-og-image.png`; export const IS_STRIPE_ENABLED = !!( process.env.STRIPE_CLIENT_ID &&