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

v3 - SEO query cleanup #765

Merged
merged 1 commit into from
Oct 14, 2024
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
92 changes: 23 additions & 69 deletions src/app/(main)/[lang]/page.tsx
Original file line number Diff line number Diff line change
@@ -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<Metadata> {
const { data: landingId } = await loadStudioQuery<string>(
LANDING_PAGE_REF_QUERY,
const { data: landingPage } = await loadStudioQuery<PageBuilder | null>(
LANDING_PAGE_QUERY,
);
const seo = await fetchSeoData(PAGE_SEO_QUERY, { id: landingId });
return generateMetadataFromSeo(seo);
return generateMetadataFromSeo(landingPage?.seo ?? null);
}

const navigationManagerLink = {
Expand All @@ -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 = (
<CustomErrorMessage
title="404 — Something went wrong"
body="The page you are looking for does not exist. There may be an error in the URL, or the page may have been moved or deleted."
link={homeLink}
/>
);

const Home = async ({ params }: Props) => {
const { perspective, isDraftMode } = getDraftModeInfo();

const language = (
await client.fetch<LanguageObject[] | null>(LANGUAGES_QUERY)
)?.find((l) => l.id === params.lang);

if (language === undefined) {
return Page404;
}

const { data: landingId } = await loadStudioQuery<string>(
LANDING_PAGE_REF_QUERY,
{},
const initialLandingPage = await loadStudioQuery<PageBuilder | null>(
LANDING_PAGE_QUERY,
{ language: params.lang },
{ perspective },
);

if (!landingId) {
if (initialLandingPage.data === null) {
return (
<InformationSection
title="Welcome! Velkommen! Välkommen!"
Expand All @@ -82,34 +49,21 @@ const Home = async ({ params }: Props) => {
);
}

const initialLandingPage = await loadStudioQuery<PageBuilder>(
PAGE_QUERY,
{ id: landingId, language: params.lang },
{ perspective },
);
const initialData = {
...initialLandingPage,
data: initialLandingPage.data,
};

if (!initialLandingPage.data) {
return (
<InformationSection
title="Landing Page is Missing Content"
body={`Your landing page is set, but it looks like there’s no content yet.\n Visit the Studio to start adding content and make your landing page come to life!`}
link={pagesLink}
/>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if landingpage is not set, how will this look like for the end user?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will display the "Welcome! Velkommen! Välkommen!" information section that is returned further up here.


return initialLandingPage.data.sections.map((section, index) => {
return (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialLandingPage}
isLandingPage={true}
sectionIndex={index}
/>
);
});
return initialLandingPage.data.sections.map((section, index) => (
<SectionRenderer
key={section._key}
section={section}
isDraftMode={isDraftMode}
initialData={initialData}
isLandingPage={true}
sectionIndex={index}
/>
));
};

export default Home;
20 changes: 3 additions & 17 deletions src/utils/seo.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { QueryParams } from "@sanity/client";
import { Metadata } from "next";

import { urlFor } from "studio/lib/image";
Expand All @@ -24,19 +23,6 @@ export const OPEN_GRAPH_IMAGE_DIMENSIONS = {
height: 630,
};

export async function fetchSeoData(
query: string,
variables?: QueryParams | undefined,
): Promise<SeoData | null> {
try {
const { data } = await loadStudioQuery<SeoData>(query, variables);
return data;
} catch (error) {
console.error("Error loading SEO data:", error);
return null;
}
}

export async function generateMetadataFromSeo(
seo: SeoData | null,
): Promise<Metadata> {
Expand All @@ -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;
Expand All @@ -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(),
Expand Down
9 changes: 3 additions & 6 deletions studio/lib/interfaces/pages.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -96,10 +98,5 @@ export interface PageBuilder {
page: string;
sections: Section[];
slug: Slug;
}

export interface SEO {
title: string;
description: string;
imageUrl?: string;
seo: SeoData;
}
9 changes: 2 additions & 7 deletions studio/lib/interfaces/seo.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
export interface SeoObject {
seoTitle?: string;
seoDescription?: string;
seoKeywords?: string;
seoImageUrl?: string;
}
import { SeoData } from "src/utils/seo";

export type DefaultSeo = {
_id: string;
_type: "seoFallback";
_createdAt: string;
_updatedAt: string;
_rev: string;
seo?: SeoObject;
seo?: SeoData;
};
29 changes: 12 additions & 17 deletions studio/lib/queries/pages.ts
Original file line number Diff line number Diff line change
@@ -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[]{
Expand Down Expand Up @@ -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`
Expand All @@ -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
}
`;
10 changes: 3 additions & 7 deletions studio/lib/queries/siteSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down Expand Up @@ -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}
}
`;