fix: og images avatars (#13790)

* fix og images avatars

* Update OgImages.tsx

* More fixes

* Update getPublicEvent.ts

* Update HeadSeo.tsx
This commit is contained in:
Omar López
2024-02-20 23:04:59 +00:00
committed by GitHub
parent 1a42b94b13
commit 73b5839284
7 changed files with 40 additions and 28 deletions
@@ -7,6 +7,7 @@ import { handleUserRedirection } from "@calcom/features/booking-redirect/handle-
import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains";
import { DEFAULT_DARK_BRAND_COLOR, DEFAULT_LIGHT_BRAND_COLOR } from "@calcom/lib/constants";
import { getUsernameList } from "@calcom/lib/defaultEvents";
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
import logger from "@calcom/lib/logger";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import { safeStringify } from "@calcom/lib/safeStringify";
@@ -206,7 +207,10 @@ export const getServerSideProps: GetServerSideProps<UserPageProps> = async (cont
const profile = {
name: user.name || user.username || "",
image: user.avatar,
image: getUserAvatarUrl({
...user,
profile: user.profile,
}),
theme: user.theme,
brandColor: user.brandColor ?? DEFAULT_LIGHT_BRAND_COLOR,
avatarUrl: user.avatarUrl,
@@ -4,7 +4,7 @@ import type { AuthOptions, Session } from "next-auth";
import { getToken } from "next-auth/jwt";
import checkLicense from "@calcom/features/ee/common/server/checkLicense";
import { WEBAPP_URL } from "@calcom/lib/constants";
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
import logger from "@calcom/lib/logger";
import { safeStringify } from "@calcom/lib/safeStringify";
import { UserRepository } from "@calcom/lib/server/repository/user";
@@ -94,7 +94,10 @@ export async function getServerSession(options: {
emailVerified: user.emailVerified,
email_verified: user.emailVerified !== null,
role: user.role,
image: `${WEBAPP_URL}/${user.username}/avatar.png`,
image: getUserAvatarUrl({
...user,
profile: user.profile,
}),
belongsToActiveTeam: token.belongsToActiveTeam,
org: token.org,
locale: user.locale ?? undefined,
@@ -8,19 +8,20 @@ import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/
import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains";
import { isRecurringEvent, parseRecurringEvent } from "@calcom/lib";
import { getDefaultEvent, getUsernameList } from "@calcom/lib/defaultEvents";
import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl";
import { getBookerBaseUrlSync } from "@calcom/lib/getBookerUrl/client";
import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML";
import { UserRepository } from "@calcom/lib/server/repository/user";
import type { PrismaClient } from "@calcom/prisma";
import type { BookerLayoutSettings } from "@calcom/prisma/zod-utils";
import {
bookerLayoutOptions,
EventTypeMetaDataSchema,
customInputSchema,
userMetadata as userMetadataSchema,
bookerLayouts as bookerLayoutsSchema,
BookerLayouts,
EventTypeMetaDataSchema,
bookerLayoutOptions,
bookerLayouts as bookerLayoutsSchema,
customInputSchema,
teamMetadataSchema,
userMetadata as userMetadataSchema,
} from "@calcom/prisma/zod-utils";
import type { UserProfile } from "@calcom/types/UserProfile";
@@ -163,7 +164,10 @@ export const getPublicEvent = async (
username: users[0].username,
name: users[0].name,
weekStart: users[0].weekStart,
image: `/${users[0].username}/avatar.png`,
image: getUserAvatarUrl({
...users[0],
profile: users[0].profile,
}),
brandColor: users[0].brandColor,
darkBrandColor: users[0].darkBrandColor,
theme: null,
+3 -3
View File
@@ -1,6 +1,6 @@
import React from "react";
import { LOGO, WEBAPP_URL } from "./constants";
import { CAL_URL, LOGO, WEBAPP_URL } from "./constants";
// Ensures tw prop is typed.
declare module "react" {
@@ -62,7 +62,7 @@ export const constructMeetingImage = (
`?type=meeting`,
`&title=${encodeURIComponent(title)}`,
`&meetingProfileName=${encodeURIComponent(profile.name)}`,
profile.image && `&meetingImage=${encodeURIComponent(WEBAPP_URL + profile.image)}`,
profile.image && `&meetingImage=${encodeURIComponent(profile.image)}`,
`${users.map((user) => `&names=${encodeURIComponent(user.name)}`).join("")}`,
`${users.map((user) => `&usernames=${encodeURIComponent(user.username)}`).join("")}`,
// Joining a multiline string for readability.
@@ -125,7 +125,7 @@ export const Meeting = ({ title, users = [], profile }: MeetingImageProps) => {
const avatars = attendees
.map((user) => {
if ("image" in user && user?.image) return user.image;
if ("username" in user && user?.username) return `${WEBAPP_URL}/${user.username}/avatar.png`;
if ("username" in user && user?.username) return `${CAL_URL}/${user.username}/avatar.png`;
return null;
})
.filter(Boolean) as string[];
+8 -4
View File
@@ -32,7 +32,11 @@ export const SENDER_NAME = process.env.NEXT_PUBLIC_SENDGRID_SENDER_NAME || "Cal.
// This is the URL from which all Cal Links and their assets are served.
// Use website URL to make links shorter(cal.com and not app.cal.com)
// As website isn't setup for preview environments, use the webapp url instead
export const CAL_URL = new URL(WEBAPP_URL).hostname.endsWith(".vercel.app") ? WEBAPP_URL : WEBSITE_URL;
// If it's a .vercel.app domain, keep it.
// Else use the website url if defined and finally fallback to the webapp url
export const CAL_URL = new URL(WEBAPP_URL).hostname.endsWith(".vercel.app")
? WEBAPP_URL
: process.env.NEXT_PUBLIC_WEBSITE_URL || WEBAPP_URL;
export const IS_CALCOM =
WEBAPP_URL &&
@@ -73,15 +77,15 @@ export const JOIN_DISCORD = "https://go.cal.com/discord";
export const POWERED_BY_URL = `${WEBSITE_URL}/?utm_source=embed&utm_medium=powered-by-button`;
export const DOCS_URL = "https://cal.com/docs";
export const DEVELOPER_DOCS = "https://developer.cal.com";
export const SEO_IMG_DEFAULT = `${WEBSITE_URL}/og-image.png`;
export const SEO_IMG_DEFAULT = `${CAL_URL}/og-image.png`;
// The Dynamic OG Image is passed through Next's Image API to further optimize it.
// 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 = `${WEBAPP_URL}/_next/image?w=1200&q=100&url=${encodeURIComponent(
export const SEO_IMG_OGIMG = `${CAL_URL}/_next/image?w=1200&q=100&url=${encodeURIComponent(
"/api/social/og/image"
)}`;
export const SEO_IMG_OGIMG_VIDEO = `${WEBSITE_URL}/video-og-image.png`;
export const SEO_IMG_OGIMG_VIDEO = `${CAL_URL}/video-og-image.png`;
export const IS_STRIPE_ENABLED = !!(
process.env.STRIPE_CLIENT_ID &&
process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY &&
+6 -6
View File
@@ -1,11 +1,11 @@
import { WEBAPP_URL } from "@calcom/lib/constants";
import { AVATAR_FALLBACK } from "@calcom/lib/constants";
import type { User, Team } from "@calcom/prisma/client";
import { AVATAR_FALLBACK, CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
import type { Team, User } from "@calcom/prisma/client";
import type { UserProfile } from "@calcom/types/UserProfile";
/**
* Gives an organization aware avatar url for a user
* It ensures that the wrong avatar isn't fetched by ensuring that organizationId is always passed
* It should always return a fully formed url
*/
export const getUserAvatarUrl = (
user:
@@ -16,11 +16,11 @@ export const getUserAvatarUrl = (
| undefined
) => {
if (user?.avatarUrl) {
return user.avatarUrl;
return CAL_URL + user.avatarUrl;
}
if (!user?.username) return AVATAR_FALLBACK;
if (!user?.username) return CAL_URL + AVATAR_FALLBACK;
// avatar.png automatically redirects to fallback avatar if user doesn't have one
return `${WEBAPP_URL}/${user.profile?.username}/avatar.png${
return `${CAL_URL}/${user.profile?.username}/avatar.png${
user.profile?.organizationId ? `?orgId=${user.profile.organizationId}` : ""
}`;
};
+3 -6
View File
@@ -4,8 +4,8 @@ import { usePathname } from "next/navigation";
import type { AppImageProps, MeetingImageProps } from "@calcom/lib/OgImages";
import { constructAppImage, constructGenericImage, constructMeetingImage } from "@calcom/lib/OgImages";
import { APP_NAME, WEBSITE_URL, IS_CALCOM } from "@calcom/lib/constants";
import { seoConfig, getSeoImage, buildCanonical } from "@calcom/lib/next-seo.config";
import { APP_NAME, CAL_URL } from "@calcom/lib/constants";
import { buildCanonical, getSeoImage, seoConfig } from "@calcom/lib/next-seo.config";
import { truncateOnWord } from "@calcom/lib/text";
export type HeadSeoProps = {
@@ -71,11 +71,8 @@ export const HeadSeo = (props: HeadSeoProps): JSX.Element => {
const path = usePathname();
// The below code sets the defaultUrl for our canonical tags
// Get the router's path
const selfHostedOrigin = WEBSITE_URL || "https://cal.com";
// Set the default URL to either the current URL (if self-hosted) or https://cal.com canonical URL
const defaultUrl = IS_CALCOM
? buildCanonical({ path, origin: "https://cal.com" })
: buildCanonical({ path, origin: selfHostedOrigin });
const defaultUrl = buildCanonical({ path, origin: CAL_URL });
const {
title,