Improve Open Graph Metas
This commit is contained in:
parent
d5e7d704bf
commit
ff89031123
|
@ -1,6 +1,8 @@
|
|||
# Generated content
|
||||
src/graphql/generated.ts
|
||||
|
||||
public/robots.txt
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
|
|
|
@ -2,6 +2,7 @@ import Head from "next/head";
|
|||
import { useSwipeable } from "react-swipeable";
|
||||
import { MaterialSymbol } from "material-symbols";
|
||||
import { atom } from "jotai";
|
||||
import { useRouter } from "next/router";
|
||||
import { layout } from "../../design.config";
|
||||
import { Ico } from "./Ico";
|
||||
import { MainPanel } from "./Panels/MainPanel";
|
||||
|
@ -54,6 +55,7 @@ export const AppLayout = ({
|
|||
const is1ColumnLayout = useAtomGetter(atoms.containerQueries.is1ColumnLayout);
|
||||
const isScreenAtLeastXs = useAtomGetter(atoms.containerQueries.isScreenAtLeastXs);
|
||||
const isIOS = useAtomGetter(isIOSAtom);
|
||||
const router = useRouter();
|
||||
|
||||
const { format } = useFormat();
|
||||
|
||||
|
@ -105,19 +107,41 @@ export const AppLayout = ({
|
|||
<title>{openGraph.title}</title>
|
||||
<meta name="description" content={openGraph.description} />
|
||||
|
||||
<meta name="twitter:site" content="@AccordsLibrary" />
|
||||
<meta name="twitter:title" content={openGraph.title} />
|
||||
<meta name="twitter:description" content={openGraph.description} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:image" content={openGraph.thumbnail.image} />
|
||||
|
||||
<meta
|
||||
property="og:type"
|
||||
content={openGraph.video ? "video.movie" : openGraph.audio ? "music.song" : "website"}
|
||||
/>
|
||||
<meta property="og:locale" content={router.locale} />
|
||||
<meta property="og:site_name" content="Accord’s Library" />
|
||||
|
||||
<meta property="og:title" content={openGraph.title} />
|
||||
<meta property="og:description" content={openGraph.description} />
|
||||
|
||||
<meta property="og:image" content={openGraph.thumbnail.image} />
|
||||
<meta property="og:image:secure_url" content={openGraph.thumbnail.image} />
|
||||
<meta property="og:image:width" content={openGraph.thumbnail.width.toString()} />
|
||||
<meta property="og:image:height" content={openGraph.thumbnail.height.toString()} />
|
||||
<meta property="og:image:alt" content={openGraph.thumbnail.alt} />
|
||||
<meta property="og:image:type" content="image/jpeg" />
|
||||
|
||||
{openGraph.audio && (
|
||||
<>
|
||||
<meta property="og:audio" content={openGraph.audio} />
|
||||
<meta property="og:audio:type" content="audio/mpeg" />
|
||||
</>
|
||||
)}
|
||||
{openGraph.video && (
|
||||
<>
|
||||
<meta property="og:video" content={openGraph.video} />{" "}
|
||||
<meta property="og:video:type" content="video/mp4" />
|
||||
</>
|
||||
)}
|
||||
</Head>
|
||||
|
||||
{/* Content panel */}
|
||||
|
|
|
@ -8,7 +8,7 @@ const DEFAULT_OG_THUMBNAIL: OgImage = {
|
|||
image: `${process.env.NEXT_PUBLIC_URL_SELF}/default_og.jpg`,
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: "Accord's Library Logo",
|
||||
alt: "Accord’s Library Logo",
|
||||
};
|
||||
|
||||
export const TITLE_PREFIX = "Accord’s Library";
|
||||
|
@ -18,13 +18,17 @@ export interface OpenGraph {
|
|||
title: string;
|
||||
description: string;
|
||||
thumbnail: OgImage;
|
||||
audio?: string;
|
||||
video?: string;
|
||||
}
|
||||
|
||||
export const getOpenGraph = (
|
||||
format: ReturnType<typeof getFormat>["format"] | ReturnType<typeof useFormat>["format"],
|
||||
title?: string | null | undefined,
|
||||
description?: string | null | undefined,
|
||||
thumbnail?: UploadImageFragment | string | null | undefined
|
||||
thumbnail?: UploadImageFragment | string | null | undefined,
|
||||
audio?: string,
|
||||
video?: string
|
||||
): OpenGraph => ({
|
||||
title: `${TITLE_PREFIX}${isDefinedAndNotEmpty(title) ? `${TITLE_SEPARATOR}${title}` : ""}`,
|
||||
description: isDefinedAndNotEmpty(description)
|
||||
|
@ -33,6 +37,8 @@ export const getOpenGraph = (
|
|||
: description
|
||||
: format("default_description"),
|
||||
thumbnail: thumbnail ? getOgImage(thumbnail) : DEFAULT_OG_THUMBNAIL,
|
||||
...(audio ? { audio } : {}),
|
||||
...(video ? { video } : {}),
|
||||
});
|
||||
|
||||
const getOgImage = (image: UploadImageFragment | string): OgImage => {
|
||||
|
|
|
@ -167,7 +167,11 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
getDescription(videos.videos.data[0].attributes.description, {
|
||||
[format("channel")]: [videos.videos.data[0].attributes.channel?.data?.attributes?.title],
|
||||
}),
|
||||
getVideoThumbnailURL(videos.videos.data[0].attributes.uid)
|
||||
getVideoThumbnailURL(videos.videos.data[0].attributes.uid),
|
||||
undefined,
|
||||
videos.videos.data[0].attributes.gone
|
||||
? getVideoFile(videos.videos.data[0].attributes.uid)
|
||||
: undefined
|
||||
),
|
||||
};
|
||||
return {
|
||||
|
|
|
@ -275,30 +275,31 @@ const Content = ({ content, ...otherProps }: Props): JSX.Element => {
|
|||
|
||||
selectedSetType === "text_set" && selectedTranslation?.text_set?.text ? (
|
||||
<Markdawn className="max-w-2xl" text={selectedTranslation.text_set.text} />
|
||||
) : selectedSetType === "audio_set" && selectedTranslation?.audio_set ? (
|
||||
) : selectedSetType === "audio_set" &&
|
||||
selectedTranslation?.audio_set &&
|
||||
selectedTranslation.language?.data?.attributes?.code ? (
|
||||
<AudioPlayer
|
||||
title={prettyInlineTitle(
|
||||
selectedTranslation.pre_title,
|
||||
selectedTranslation.title,
|
||||
selectedTranslation.subtitle
|
||||
)}
|
||||
src={`${process.env.NEXT_PUBLIC_URL_ASSETS}/contents/audios/\
|
||||
${content.slug}_${selectedTranslation.language?.data?.attributes?.code}.mp3`}
|
||||
src={getAudioURL(content.slug, selectedTranslation.language.data.attributes.code)}
|
||||
className="max-w-2xl"
|
||||
/>
|
||||
) : (
|
||||
selectedSetType === "video_set" &&
|
||||
selectedTranslation?.video_set && (
|
||||
selectedTranslation?.video_set &&
|
||||
selectedTranslation.language?.data?.attributes?.code && (
|
||||
<VideoPlayer
|
||||
title={prettyInlineTitle(
|
||||
selectedTranslation.pre_title,
|
||||
selectedTranslation.title,
|
||||
selectedTranslation.subtitle
|
||||
)}
|
||||
src={`${process.env.NEXT_PUBLIC_URL_ASSETS}/contents/videos/\
|
||||
${content.slug}_${selectedTranslation.language?.data?.attributes?.code}.mp4`}
|
||||
src={getVideoURL(content.slug, selectedTranslation.language.data.attributes.code)}
|
||||
subSrc={`${process.env.NEXT_PUBLIC_URL_ASSETS}/contents/videos/\
|
||||
${content.slug}_${selectedTranslation.language?.data?.attributes?.code}.vtt`}
|
||||
${content.slug}_${selectedTranslation.language.data.attributes.code}.vtt`}
|
||||
className="max-w-[90vh]"
|
||||
/>
|
||||
)
|
||||
|
@ -340,7 +341,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
return { notFound: true };
|
||||
}
|
||||
|
||||
const { title, description } = (() => {
|
||||
const { title, description, audio, video } = (() => {
|
||||
if (context.locale && context.locales) {
|
||||
const selectedTranslation = staticSmartLanguage({
|
||||
items: content.contents.data[0].attributes.translations,
|
||||
|
@ -351,6 +352,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
const rawDescription = isDefinedAndNotEmpty(selectedTranslation.description)
|
||||
? selectedTranslation.description
|
||||
: selectedTranslation.text_set?.text;
|
||||
|
||||
return {
|
||||
title: prettyInlineTitle(
|
||||
selectedTranslation.pre_title,
|
||||
|
@ -366,12 +368,22 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
["attributes"]
|
||||
).map((category) => category.attributes.short),
|
||||
}),
|
||||
audio:
|
||||
selectedTranslation.language?.data?.attributes?.code && selectedTranslation.audio_set
|
||||
? getAudioURL(slug, selectedTranslation.language.data.attributes.code)
|
||||
: undefined,
|
||||
video:
|
||||
selectedTranslation.language?.data?.attributes?.code && selectedTranslation.video_set
|
||||
? getVideoURL(slug, selectedTranslation.language.data.attributes.code)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
title: prettySlug(content.contents.data[0].attributes.slug),
|
||||
description: undefined,
|
||||
audio: undefined,
|
||||
video: undefined,
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -379,7 +391,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
|
||||
const props: Props = {
|
||||
content: content.contents.data[0].attributes as ContentWithTranslations,
|
||||
openGraph: getOpenGraph(format, title, description, thumbnail),
|
||||
openGraph: getOpenGraph(format, title, description, thumbnail, audio, video),
|
||||
};
|
||||
return {
|
||||
props: props,
|
||||
|
@ -488,3 +500,16 @@ const RelatedContentPreview = ({
|
|||
/>
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
* ╭───────────────────╮
|
||||
* ─────────────────────────────────────╯ PRIVATE METHODS ╰───────────────────────────────────────
|
||||
*/
|
||||
|
||||
const getAudioURL = (slug: string, langCode: string): string =>
|
||||
`${process.env.NEXT_PUBLIC_URL_ASSETS}/contents/audios/\
|
||||
${slug}_${langCode}.mp3`;
|
||||
|
||||
const getVideoURL = (slug: string, langCode: string): string =>
|
||||
`${process.env.NEXT_PUBLIC_URL_ASSETS}/contents/videos/\
|
||||
${slug}_${langCode}.mp4`;
|
||||
|
|
Loading…
Reference in New Issue