From 132b471d1ab890ecbaccbeb989cd2d8555a80abe Mon Sep 17 00:00:00 2001 From: Mathias Oterhals Myklebust <24361490+mathiazom@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:54:46 +0000 Subject: [PATCH] feat(seo): cleanup metadata fetching for layout and pages (#765) --- src/app/(main)/[lang]/page.tsx | 92 ++++++++---------------------- src/utils/seo.ts | 20 +------ studio/lib/interfaces/pages.ts | 9 +-- studio/lib/interfaces/seo.ts | 9 +-- studio/lib/queries/pages.ts | 29 ++++------ studio/lib/queries/siteSettings.ts | 10 +--- 6 files changed, 46 insertions(+), 123 deletions(-) diff --git a/src/app/(main)/[lang]/page.tsx b/src/app/(main)/[lang]/page.tsx index a26193826..a8717006d 100644 --- a/src/app/(main)/[lang]/page.tsx +++ b/src/app/(main)/[lang]/page.tsx @@ -1,28 +1,19 @@ import { Metadata } from "next"; -import CustomErrorMessage from "src/components/customErrorMessage/CustomErrorMessage"; import InformationSection from "src/components/informationSection/InformationSection"; -import { homeLink } from "src/components/utils/linkTypes"; import { getDraftModeInfo } from "src/utils/draftmode"; import SectionRenderer from "src/utils/renderSection"; -import { fetchSeoData, generateMetadataFromSeo } from "src/utils/seo"; -import { client } from "studio/lib/client"; +import { generateMetadataFromSeo } from "src/utils/seo"; import { LinkType } from "studio/lib/interfaces/navigation"; import { PageBuilder } from "studio/lib/interfaces/pages"; -import { LanguageObject } from "studio/lib/interfaces/supportedLanguages"; -import { PAGE_QUERY, PAGE_SEO_QUERY } from "studio/lib/queries/pages"; -import { - LANDING_PAGE_REF_QUERY, - LANGUAGES_QUERY, -} from "studio/lib/queries/siteSettings"; +import { LANDING_PAGE_QUERY } from "studio/lib/queries/siteSettings"; import { loadStudioQuery } from "studio/lib/store"; export async function generateMetadata(): Promise { - const { data: landingId } = await loadStudioQuery( - LANDING_PAGE_REF_QUERY, + const { data: landingPage } = await loadStudioQuery( + LANDING_PAGE_QUERY, ); - const seo = await fetchSeoData(PAGE_SEO_QUERY, { id: landingId }); - return generateMetadataFromSeo(seo); + return generateMetadataFromSeo(landingPage?.seo ?? null); } const navigationManagerLink = { @@ -33,44 +24,20 @@ const navigationManagerLink = { internalLink: { _ref: "studio/structure/siteSettings;navigationManager" }, }; -const pagesLink = { - _key: "go-to-pages", - _type: "link", - linkTitle: "Go to Pages Manager", - linkType: LinkType.Internal, - internalLink: { _ref: "studio/structure/pages" }, -}; - type Props = { params: { lang: string; slug: string }; }; -const Page404 = ( - -); - const Home = async ({ params }: Props) => { const { perspective, isDraftMode } = getDraftModeInfo(); - const language = ( - await client.fetch(LANGUAGES_QUERY) - )?.find((l) => l.id === params.lang); - - if (language === undefined) { - return Page404; - } - - const { data: landingId } = await loadStudioQuery( - LANDING_PAGE_REF_QUERY, - {}, + const initialLandingPage = await loadStudioQuery( + LANDING_PAGE_QUERY, + { language: params.lang }, { perspective }, ); - if (!landingId) { + if (initialLandingPage.data === null) { return ( { ); } - const initialLandingPage = await loadStudioQuery( - PAGE_QUERY, - { id: landingId, language: params.lang }, - { perspective }, - ); + const initialData = { + ...initialLandingPage, + data: initialLandingPage.data, + }; - if (!initialLandingPage.data) { - return ( - - ); - } - - return initialLandingPage.data.sections.map((section, index) => { - return ( - - ); - }); + return initialLandingPage.data.sections.map((section, index) => ( + + )); }; export default Home; diff --git a/src/utils/seo.ts b/src/utils/seo.ts index 809605cca..f0ecc9196 100644 --- a/src/utils/seo.ts +++ b/src/utils/seo.ts @@ -1,4 +1,3 @@ -import type { QueryParams } from "@sanity/client"; import { Metadata } from "next"; import { urlFor } from "studio/lib/image"; @@ -24,19 +23,6 @@ export const OPEN_GRAPH_IMAGE_DIMENSIONS = { height: 630, }; -export async function fetchSeoData( - query: string, - variables?: QueryParams | undefined, -): Promise { - try { - const { data } = await loadStudioQuery(query, variables); - return data; - } catch (error) { - console.error("Error loading SEO data:", error); - return null; - } -} - export async function generateMetadataFromSeo( seo: SeoData | null, ): Promise { @@ -52,10 +38,10 @@ export async function generateMetadataFromSeo( const title = seo?.title || - defaultSeo?.seo?.seoTitle || + defaultSeo?.seo?.title || companyInfo?.companyName || "Variant"; - const description = seo?.description || defaultSeo?.seo?.seoDescription; + const description = seo?.description || defaultSeo?.seo?.description; const keywords = seo?.keywords || ""; const favicon = brandAssets?.favicon; @@ -69,7 +55,7 @@ export async function generateMetadataFromSeo( title: title, ...(description ? { description: description } : {}), })}`; - const sanityImageUrl = seo?.imageUrl || defaultSeo?.seo?.seoImageUrl; + const sanityImageUrl = seo?.imageUrl || defaultSeo?.seo?.imageUrl; const sanityImageParams = `?${new URLSearchParams({ w: OPEN_GRAPH_IMAGE_DIMENSIONS.width.toString(), h: OPEN_GRAPH_IMAGE_DIMENSIONS.height.toString(), diff --git a/studio/lib/interfaces/pages.ts b/studio/lib/interfaces/pages.ts index b0415b625..77e571bbd 100644 --- a/studio/lib/interfaces/pages.ts +++ b/studio/lib/interfaces/pages.ts @@ -1,5 +1,7 @@ import { PortableTextBlock } from "sanity"; +import { SeoData } from "src/utils/seo"; + import { Slug } from "./global"; import { IImage, ImageExtendedProps } from "./media"; import { ILink } from "./navigation"; @@ -96,10 +98,5 @@ export interface PageBuilder { page: string; sections: Section[]; slug: Slug; -} - -export interface SEO { - title: string; - description: string; - imageUrl?: string; + seo: SeoData; } diff --git a/studio/lib/interfaces/seo.ts b/studio/lib/interfaces/seo.ts index 59c5c4f12..267cf1ce3 100644 --- a/studio/lib/interfaces/seo.ts +++ b/studio/lib/interfaces/seo.ts @@ -1,9 +1,4 @@ -export interface SeoObject { - seoTitle?: string; - seoDescription?: string; - seoKeywords?: string; - seoImageUrl?: string; -} +import { SeoData } from "src/utils/seo"; export type DefaultSeo = { _id: string; @@ -11,5 +6,5 @@ export type DefaultSeo = { _createdAt: string; _updatedAt: string; _rev: string; - seo?: SeoObject; + seo?: SeoData; }; diff --git a/studio/lib/queries/pages.ts b/studio/lib/queries/pages.ts index 0e4c73fa6..a2647771d 100644 --- a/studio/lib/queries/pages.ts +++ b/studio/lib/queries/pages.ts @@ -1,6 +1,7 @@ import { groq } from "next-sanity"; import { LANGUAGE_FIELD_FRAGMENT, TRANSLATED_LINK_FRAGMENT } from "./i18n"; +import { translatedFieldFragment } from "./utils/i18n"; const SECTIONS_FRAGMENT = groq` sections[]{ @@ -36,10 +37,20 @@ const SECTIONS_FRAGMENT = groq` } `; +export const SEO_FRAGMENT = groq` + "seo": ${translatedFieldFragment("seo")} { + "title": seoTitle, + "description": seoDescription, + "imageUrl": seoImage.asset->url, + "keywords": seoKeywords + }, +`; + export const PAGE_FRAGMENT = groq` ..., ${LANGUAGE_FIELD_FRAGMENT}, - ${SECTIONS_FRAGMENT} + ${SECTIONS_FRAGMENT}, + ${SEO_FRAGMENT} `; export const PAGE_QUERY = groq` @@ -48,24 +59,8 @@ export const PAGE_QUERY = groq` } `; -export const PAGE_SEO_QUERY = groq` - *[_type == "pageBuilder" && _id == $id][0]{ - "title": seo.seoTitle, - "description": seo.seoDescription, - "imageUrl": seo.seoImage.asset->url - } -`; - export const PAGE_BY_SLUG_QUERY = groq` *[_type == "pageBuilder" && slug.current == $slug][0]{ ${PAGE_FRAGMENT} } `; - -export const SEO_SLUG_QUERY = groq` - *[defined(seo) && slug.current == $slug][0]{ - "title": seo.seoTitle, - "description": seo.seoDescription, - "imageUrl": seo.seoImage.asset->url - } -`; diff --git a/studio/lib/queries/siteSettings.ts b/studio/lib/queries/siteSettings.ts index ea7722032..a207f0cbf 100644 --- a/studio/lib/queries/siteSettings.ts +++ b/studio/lib/queries/siteSettings.ts @@ -5,7 +5,7 @@ import { TRANSLATED_LINK_FRAGMENT, TRANSLATED_SLUG_VALUE_FRAGMENT, } from "./i18n"; -import { PAGE_FRAGMENT } from "./pages"; +import { PAGE_FRAGMENT, SEO_FRAGMENT } from "./pages"; //Brand Assets export const BRAND_ASSETS_QUERY = groq` @@ -63,11 +63,7 @@ export const DEFAULT_LANGUAGE_QUERY = groq` //Default SEO export const DEFAULT_SEO_QUERY = groq` *[_type == "seoFallback"][0]{ - seo { - seoTitle, - seoDescription, - seoKeywords, - "seoImageUrl": seoImage.asset->url - } + ..., + ${SEO_FRAGMENT} } `;