Skip to content

Commit

Permalink
v3 - support nested slugs in sitemap (#776)
Browse files Browse the repository at this point in the history
* feat(sitemap): handle nested slug

* refactor(sitemap): token → studioToken
  • Loading branch information
mathiazom authored Oct 14, 2024
1 parent dd1db85 commit 9b77b65
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 29 deletions.
154 changes: 131 additions & 23 deletions src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,149 @@
import type { MetadataRoute } from "next";

import { client } from "studio/lib/client";
import { DocumentWithSlug } from "studio/lib/interfaces/global";
import { PageBuilder } from "studio/lib/interfaces/pages";
import { DOCUMENTS_WITH_SLUG_QUERY } from "studio/lib/queries/siteMap";
import { LANDING_PAGE_QUERY } from "studio/lib/queries/siteSettings";
import { token } from "studio/lib/token";
import {
DocumentTranslatedSitemapData,
FieldTranslatedSitemapData,
SitemapBaseData,
UntranslatedSitemapData,
} from "studio/lib/interfaces/sitemap";
import { LanguageObject } from "studio/lib/interfaces/supportedLanguages";
import { LEGAL_DOCUMENTS_SITEMAP_QUERY } from "studio/lib/queries/admin";
import { PAGES_SITEMAP_QUERY } from "studio/lib/queries/pages";
import {
LANDING_PAGE_SITEMAP_QUERY,
LANGUAGES_QUERY,
} from "studio/lib/queries/siteSettings";
import {
COMPENSATIONS_PAGE_SITEMAP_QUERY,
CUSTOMER_CASES_PAGE_SITEMAP_QUERY,
} from "studio/lib/queries/specialPages";
import { token as studioToken } from "studio/lib/token";
import { sharedClient } from "studioShared/lib/client";
import { CUSTOMER_CASES_SITEMAP_QUERY } from "studioShared/lib/queries/customerCases";
import { token as sharedToken } from "studioShared/lib/token";

import { readBaseUrl } from "./env";

const clientWithToken = client.withConfig({ token });
const clientWithToken = client.withConfig({ token: studioToken });
const sharedClientWithToken = sharedClient.withConfig({ token: sharedToken });

export const dynamic = "force-dynamic";
export const fetchCache = "default-no-store";

type RelativeSiteMap = {
relativeUrl: string;
lastModified: Date;
}[];

async function landingPageSitemap(): Promise<RelativeSiteMap> {
const languages = await clientWithToken.fetch<LanguageObject[] | null>(
LANGUAGES_QUERY,
);
const page = await clientWithToken.fetch<SitemapBaseData | null>(
LANDING_PAGE_SITEMAP_QUERY,
);
if (languages !== null && page !== null) {
const siteMap = languages.map((language) => ({
relativeUrl: language.id,
lastModified: new Date(page._updatedAt),
}));
siteMap.push({
relativeUrl: "",
lastModified: new Date(page._updatedAt),
});
return siteMap;
}
return [];
}

async function compensationsPageSitemap(): Promise<RelativeSiteMap> {
const page = await clientWithToken.fetch<FieldTranslatedSitemapData | null>(
COMPENSATIONS_PAGE_SITEMAP_QUERY,
);
if (page?.slug !== undefined) {
return page.slug.map((slug) => {
return {
relativeUrl: `${slug._key}/${slug.value}`,
lastModified: new Date(page._updatedAt),
};
});
}
return [];
}

async function dynamicPagesSitemap(): Promise<RelativeSiteMap> {
const pages = await clientWithToken.fetch<UntranslatedSitemapData[] | null>(
PAGES_SITEMAP_QUERY,
);
if (pages !== null) {
return pages.map((page) => ({
relativeUrl: page.slug.current,
lastModified: new Date(page._updatedAt),
}));
}
return [];
}

async function customerCasesSitemap(): Promise<RelativeSiteMap> {
const page = await clientWithToken.fetch<UntranslatedSitemapData | null>(
CUSTOMER_CASES_PAGE_SITEMAP_QUERY,
);
if (page !== null) {
const siteMap = [
{
relativeUrl: page.slug.current,
lastModified: new Date(page._updatedAt),
},
];
const cases = await sharedClientWithToken.fetch<
DocumentTranslatedSitemapData[] | null
>(CUSTOMER_CASES_SITEMAP_QUERY);
if (cases !== null) {
siteMap.push(
...cases.map((customerCase) => ({
relativeUrl: `${customerCase.language}/${page.slug.current}/${customerCase.slug.current}`,
lastModified: new Date(customerCase._updatedAt),
})),
);
}
return siteMap;
}
return [];
}

async function legalDocumentsSitemap(): Promise<RelativeSiteMap> {
const pages = await clientWithToken.fetch<
DocumentTranslatedSitemapData[] | null
>(LEGAL_DOCUMENTS_SITEMAP_QUERY);
if (pages !== null) {
return pages.map((page) => ({
relativeUrl: `${page.language}/${page.slug.current}`,
lastModified: new Date(page._updatedAt),
}));
}
return [];
}

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrlResult = readBaseUrl();
if (!baseUrlResult.ok) {
console.error("Failed to generate sitemap:", baseUrlResult.error);
return [];
}
const baseUrl = baseUrlResult.value;
const slugDocuments = await clientWithToken.fetch<DocumentWithSlug[]>(
DOCUMENTS_WITH_SLUG_QUERY,
);
const sitemapEntries = slugDocuments.map((slugDocument) => ({
url: new URL(slugDocument.slug.current, baseUrl).toString(),
lastModified: new Date(slugDocument._updatedAt),
}));
const landingPage = await clientWithToken.fetch<PageBuilder | null>(
LANDING_PAGE_QUERY,
);
if (landingPage !== null) {
sitemapEntries.push({
url: baseUrl.toString(),
lastModified: new Date(landingPage._updatedAt),
});
}
return sitemapEntries;
return (
await Promise.all([
landingPageSitemap(),
compensationsPageSitemap(),
dynamicPagesSitemap(),
customerCasesSitemap(),
legalDocumentsSitemap(),
])
)
.flat()
.map(({ lastModified, relativeUrl }) => ({
url: new URL(relativeUrl, baseUrl).toString(),
lastModified,
}));
}
4 changes: 2 additions & 2 deletions src/components/compensations/CompensationsPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";
import { COMPANY_LOCATIONS_QUERY } from "studio/lib/queries/admin";
import { LOCALE_QUERY } from "studio/lib/queries/locale";
import { COMPENSATIONS_PAGE_QUERY } from "studio/lib/queries/specialPages";
import { COMPENSATIONS_PAGE_BY_SLUG_QUERY } from "studio/lib/queries/specialPages";

import Compensations from "./Compensations";

Expand All @@ -24,7 +24,7 @@ const CompensationsPreview = ({
initialLocale,
}: CompensationsPreviewProps) => {
const { data: compensationsData } = useQuery<CompensationsPage>(
COMPENSATIONS_PAGE_QUERY,
COMPENSATIONS_PAGE_BY_SLUG_QUERY,
{
slug: initialCompensations.data.slug,
language: initialCompensations.data.language,
Expand Down
6 changes: 3 additions & 3 deletions src/utils/pageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { LOCALE_QUERY } from "studio/lib/queries/locale";
import { PAGE_BY_SLUG_QUERY } from "studio/lib/queries/pages";
import {
COMPENSATIONS_PAGE_QUERY,
COMPENSATIONS_PAGE_BY_SLUG_QUERY,
CUSTOMER_CASES_PAGE_QUERY,
} from "studio/lib/queries/specialPages";
import { loadStudioQuery } from "studio/lib/store";
Expand Down Expand Up @@ -89,7 +89,7 @@ async function fetchCompensationsPage({
};
const compensationsPageResult =
await loadStudioQuery<CompensationsPage | null>(
COMPENSATIONS_PAGE_QUERY,
COMPENSATIONS_PAGE_BY_SLUG_QUERY,
queryParams,
{
perspective,
Expand All @@ -115,7 +115,7 @@ async function fetchCompensationsPage({
return null;
}
return {
query: COMPENSATIONS_PAGE_QUERY,
query: COMPENSATIONS_PAGE_BY_SLUG_QUERY,
queryParams,
queryResponse: {
compensationsPage: {
Expand Down
17 changes: 17 additions & 0 deletions studio/lib/interfaces/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { InternationalizedString, Slug } from "./global";

export interface SitemapBaseData {
_updatedAt: string;
}

export interface FieldTranslatedSitemapData extends SitemapBaseData {
slug: InternationalizedString;
}

export interface UntranslatedSitemapData extends SitemapBaseData {
slug: Slug;
}

export interface DocumentTranslatedSitemapData extends UntranslatedSitemapData {
language: string;
}
8 changes: 8 additions & 0 deletions studio/lib/queries/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ export const COMPANY_LOCATIONS_QUERY = groq`*[_type == "companyLocation"]`;
export const LEGAL_DOCUMENTS_BY_LANG_QUERY = groq`*[_type == "legalDocument" && language == $language]`;

export const LEGAL_DOCUMENT_BY_SLUG_AND_LANG_QUERY = groq`*[_type == "legalDocument" && language == $language && slug.current == $slug][0]`;

export const LEGAL_DOCUMENTS_SITEMAP_QUERY = groq`
*[_type == "legalDocument"] {
_updatedAt,
language,
slug
}
`;
15 changes: 15 additions & 0 deletions studio/lib/queries/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ export const PAGE_QUERY = groq`
}
`;

export const PAGES_SITEMAP_QUERY = groq`
*[_type == "pageBuilder"]{
_updatedAt,
slug
}
`;

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}
Expand Down
6 changes: 6 additions & 0 deletions studio/lib/queries/siteSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ export const LANDING_PAGE_QUERY = groq`
}
`;

export const LANDING_PAGE_SITEMAP_QUERY = groq`
*[_type == "navigationManager"][0].setLanding -> {
_updatedAt
}
`;

//Social Media Profiles
export const SOME_PROFILES_QUERY = groq`
*[_type == "soMeLinksID" && _id == "soMeLinksID"][0]
Expand Down
15 changes: 14 additions & 1 deletion studio/lib/queries/specialPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { groq } from "next-sanity";
import { translatedFieldFragment } from "./utils/i18n";

//Compensations
export const COMPENSATIONS_PAGE_QUERY = groq`
export const COMPENSATIONS_PAGE_BY_SLUG_QUERY = groq`
*[_type == "compensations" && ${translatedFieldFragment("slug")} == $slug][0] {
...,
"language": $language,
Expand All @@ -25,7 +25,20 @@ export const COMPENSATIONS_PAGE_QUERY = groq`
},
}
`;
export const COMPENSATIONS_PAGE_SITEMAP_QUERY = groq`
*[_type == "compensations"][0] {
_updatedAt,
slug
}
`;

//Customer Cases
export const CUSTOMER_CASES_PAGE_QUERY = groq`
*[_type == "customerCasesPage" && slug.current == $slug][0]`;

export const CUSTOMER_CASES_PAGE_SITEMAP_QUERY = groq`
*[_type == "customerCasesPage"][0] {
_updatedAt,
slug
}
`;
8 changes: 8 additions & 0 deletions studioShared/lib/queries/customerCases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ export const CUSTOMER_CASES_QUERY = groq`*[_type == "customerCase" && language =
`;

export const CUSTOMER_CASE_QUERY = groq`*[_type == "customerCase" && slug.current == $slug && language == $language][0]`;

export const CUSTOMER_CASES_SITEMAP_QUERY = groq`
*[_type == "customerCase"] {
_updatedAt,
language,
slug
}
`;

0 comments on commit 9b77b65

Please sign in to comment.