Skip to content

[Appdir] Sitemap for new setup #3779

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

Merged
merged 9 commits into from
May 15, 2025
107 changes: 107 additions & 0 deletions aksel.nav.no/website/app/_sanity/live-fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import "server-only";
import { sanityFetch } from "@/app/_sanity/live";
import {
DESIGNSYSTEM_GRUNNLEGGENDE_LANDINGPAGE_QUERY,
DESIGNSYSTEM_KOMPONENTER_LANDINGPAGE_QUERY,
DESIGNSYSTEM_TEMPLATES_LANDINGPAGE_QUERY,
GOD_PRAKSIS_ALL_TEMA_QUERY,
SITEMAP_ARTICLES_BY_TYPE_QUERY,
SITEMAP_LANDINGPAGES_QUERY,
} from "@/app/_sanity/queries";
import { PAGE_ROUTES } from "@/app/routing-config";
import { allArticleDocuments } from "@/sanity/config";

async function fetchAllSanityPages(): Promise<
{
slug: string;
lastMod: string | null;
}[]
> {
const [
{ data: landingPageData },
{ data: articleListData },
{ data: temaListData },
{ data: dsKomponenterData },
{ data: dsGrunnleggendeData },
{ data: dsTemplatesData },
] = await Promise.all([
sanityFetch({
query: SITEMAP_LANDINGPAGES_QUERY,
stega: false,
perspective: "published",
}),
sanityFetch({
query: SITEMAP_ARTICLES_BY_TYPE_QUERY,
params: {
doctypes: allArticleDocuments,
},
stega: false,
perspective: "published",
}),
sanityFetch({
query: GOD_PRAKSIS_ALL_TEMA_QUERY,
stega: false,
perspective: "published",
}),
sanityFetch({
query: DESIGNSYSTEM_KOMPONENTER_LANDINGPAGE_QUERY,
stega: false,
perspective: "published",
}),
sanityFetch({
query: DESIGNSYSTEM_GRUNNLEGGENDE_LANDINGPAGE_QUERY,
stega: false,
perspective: "published",
}),
sanityFetch({
query: DESIGNSYSTEM_TEMPLATES_LANDINGPAGE_QUERY,
stega: false,
perspective: "published",
}),
]);

const paths = [
{ slug: "", lastMod: landingPageData.frontpage },
{ slug: "/god-praksis", lastMod: landingPageData.godpraksis },
{ slug: "/produktbloggen", lastMod: landingPageData.blogg },
{ slug: "/designsystemet", lastMod: new Date().toISOString() },
...articleListData.map((page) => {
return { slug: `/${page.slug}`, lastMod: page._updatedAt };
}),
...temaListData
.filter((tema) => tema.articles.length > 0)
.map((page) => {
return { slug: `/god-praksis/${page.slug}`, lastMod: page._updatedAt };
}),
];

dsKomponenterData?.overview_pages?.forEach((overviewPage) => {
paths.push({ slug: `/komponenter/${overviewPage}`, lastMod: null });
});

dsGrunnleggendeData?.overview_pages?.forEach((overviewPage) => {
paths.push({ slug: `/grunnleggende/${overviewPage}`, lastMod: null });
});

dsTemplatesData?.overview_pages?.forEach((overviewPage) => {
paths.push({ slug: `/monster-maler/${overviewPage}`, lastMod: null });
});

Object.values(PAGE_ROUTES).forEach((category) => {
category.root.forEach((page) =>
paths.push({ slug: `/${page.slug}`, lastMod: null }),
);

if (category?.nested) {
Object.values(category.nested).forEach((nestedCategory) => {
nestedCategory.forEach((page) =>
paths.push({ slug: `/${page.slug}`, lastMod: null }),
);
});
}
});

return paths;
}

export { fetchAllSanityPages };
19 changes: 19 additions & 0 deletions aksel.nav.no/website/app/_sanity/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ const SLUG_BY_TYPE_QUERY = defineQuery(`
const GOD_PRAKSIS_ALL_TEMA_QUERY =
defineQuery(`*[_type == "gp.tema"] | order(lower(title)){
title,
_updatedAt,
description,
pictogram,
"slug": slug.current,
Expand Down Expand Up @@ -262,6 +263,22 @@ const DOCUMENT_BY_ID_FOR_SLACK_QUERY = defineQuery(`*[_id == $id][0]{
"contacts": undertema[]->tema->contacts[]->email
}`);

/* --------------------------------- Sitemap -------------------------------- */
const SITEMAP_LANDINGPAGES_QUERY = defineQuery(`
{
"frontpage": *[_type == "aksel_forside"][0]._updatedAt,
"godpraksis": *[_type == "godpraksis_landingsside"][0]._updatedAt,
"blogg": *[_type == "blogg_landingsside"][0]._updatedAt,
}
`);

const SITEMAP_ARTICLES_BY_TYPE_QUERY = defineQuery(`
*[_type in $doctypes]{
"slug": slug.current,
_updatedAt
}
`);

/* --------------------------------- Exports -------------------------------- */
export {
DESIGNSYSTEM_SIDEBAR_QUERY,
Expand All @@ -288,4 +305,6 @@ export {
DOCUMENT_BY_ID_FOR_SLACK_QUERY,
SIDE_ARTICLE_BY_SLUG_QUERY,
PRINSIPPER_BY_SLUG_QUERY,
SITEMAP_LANDINGPAGES_QUERY,
SITEMAP_ARTICLES_BY_TYPE_QUERY,
};
26 changes: 24 additions & 2 deletions aksel.nav.no/website/app/_sanity/query-types.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { stegaClean } from "next-sanity";
import { useId } from "react";
import { BodyShort, Detail } from "@navikt/ds-react";
import { DesignsystemSidebarSectionT } from "@/types";
Expand All @@ -16,16 +15,10 @@ function DesignsystemSidebarGroup(props: DesignsystemSidebarGroupT) {
const { label, links, layout } = props;
const id = useId();

const isDarkside = stegaClean(label.toLowerCase()) === "darkside";

const LabelComponent = layout === "sidebar" ? Detail : BodyShort;

return (
<li
className={styles.navListGroup}
data-type={isDarkside ? "darkside" : "neutral"}
data-layout={layout}
>
<li className={styles.navListGroup} data-layout={layout}>
<LabelComponent
as="div"
className={styles.navListGroupLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@

.navListGroup {
border-radius: var(--ax-border-radius-medium);

&[data-type="darkside"] {
background-color: var(--ax-bg-brand-magenta-moderate);
}
}

.navListGroupLabel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ function DesignsystemSidebarSubNav(
const { pages, title, layout } = props;
const pathName = usePathname();

const isDarkside = title.toLowerCase() === "darkside";

const isSectionActive = pages.some((page) => {
return pathName?.split("#")[0] === stegaClean(`/${page.slug}`);
});

const [open, setOpen] = useState(isSectionActive);

return (
<li>
<li data-type={isDarkside ? "darkside" : "neutral"}>
<button
onClick={() => {
setOpen(!open);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,32 @@ import {
DESIGNSYSTEM_OVERVIEW_PAGES_QUERYResult,
DESIGNSYSTEM_SIDEBAR_QUERYResult,
} from "@/app/_sanity/query-types";
import { PAGE_ROUTES } from "@/app/routing-config";
import { sanityCategoryLookup } from "@/sanity/config";
import { DesignsystemSidebarSectionT, SidebarPageT } from "@/types";

/**
* TODO: We currently do not support sorting "unique" pages
*/
const pageTypes = {
grunnleggende: {
name: "Grunnleggende",
_type: "ds_artikkel",
uniquePages: [],
},
komponenter: {
name: "Komponenter",
_type: "komponent_artikkel",
uniquePages: [
{
heading: "Ikoner",
slug: "komponenter/ikoner",
tag: "ready",
},
],
},
templates: {
name: "Mønster og Maler",
_type: "templates_artikkel",
uniquePages: [],
},
} as const;

type DesignsystemSidebarDataT = {
label: string;
links: DesignsystemSidebarSectionT;
}[];

function typedKeys<T extends object>(obj: T): (keyof T)[] {
return Object.keys(obj) as (keyof T)[];
}

function generateSidebar(
input: DESIGNSYSTEM_SIDEBAR_QUERYResult,
overviewPages: DESIGNSYSTEM_OVERVIEW_PAGES_QUERYResult,
): DesignsystemSidebarDataT {
return Object.keys(pageTypes).map((type) => {
return typedKeys(PAGE_ROUTES).map((type) => {
const overviewPageList = overviewPages.find((page) =>
stegaClean(page._type).includes(type),
)?.overview_pages;

const categories = sanityCategoryLookup(type as keyof typeof pageTypes);
const categories = sanityCategoryLookup(type);

const filteredInput = input.filter(
(doc) => stegaClean(doc._type) === pageTypes[type]._type,
(doc) => stegaClean(doc._type) === PAGE_ROUTES[type]._type,
);

const standalonePages: SidebarPageT[] = filteredInput
Expand Down Expand Up @@ -79,7 +58,6 @@ function generateSidebar(
.sort(sortIndex)
.sort(sortDeprecated),
}))
.filter((category) => !(!category.pages || category.pages.length === 0))
.map((category) => {
const hasOverviewPage = overviewPageList?.some(
(page) => stegaClean(category.value) === page,
Expand All @@ -99,45 +77,23 @@ function generateSidebar(
});
}

if (type === "grunnleggende" && category.value === "darkside") {
pages.push({
heading: "Tokens darkside",
slug: `${type}/${category.value}/design-tokens`,
tag: "ready",
});
if (
PAGE_ROUTES[type].nested &&
category.value in PAGE_ROUTES[type].nested
) {
pages.push(...PAGE_ROUTES[type].nested[category.value]);
}

return {
...category,
pages,
};
});

// TODO: Remove this when we have published any darkside pages from Sanity, so the entry above is activated
if (
type === "grunnleggende" &&
!groupedPages.some((page) => page.value === "darkside")
) {
groupedPages.push({
title: "Darkside",
value: "darkside",
pages: [
{
heading: "Design tokens",
slug: `${type}/darkside/design-tokens`,
tag: "ready",
},
],
});
}
})
.filter((category) => category.pages.length > 0);

return {
label: pageTypes[type].name,
links: [
...pageTypes[type].uniquePages,
...standalonePages,
...groupedPages,
],
label: PAGE_ROUTES[type].title,
links: [...PAGE_ROUTES[type].root, ...standalonePages, ...groupedPages],
};
});
}
Expand Down
11 changes: 11 additions & 0 deletions aksel.nav.no/website/app/dev/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { MetadataRoute } from "next";
import { fetchAllSanityPages } from "@/app/_sanity/live-fetch";

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const pages = await fetchAllSanityPages();

return pages.map((page) => ({
url: `https://www.aksel.nav.no${page.slug}`,
lastModified: page?.lastMod?.split("T")[0] ?? undefined,
}));
}
Loading
Loading