From 057b8c24a7e45569d03ab00edb49f920d4712fc2 Mon Sep 17 00:00:00 2001 From: Franz Unger Date: Wed, 18 Dec 2024 12:48:10 +0100 Subject: [PATCH] Static rendering (#576) --- site/src/app/[domain]/[language]/layout.tsx | 2 + .../src/app/[domain]/[language]/not-found.tsx | 27 ++++++++-- site/src/app/not-found.tsx | 10 ---- site/src/documents/NotFound.tsx | 49 +++++++++++++++++++ site/src/util/NotFoundContext.tsx | 25 ++++++++++ 5 files changed, 98 insertions(+), 15 deletions(-) delete mode 100644 site/src/app/not-found.tsx create mode 100644 site/src/documents/NotFound.tsx create mode 100644 site/src/util/NotFoundContext.tsx diff --git a/site/src/app/[domain]/[language]/layout.tsx b/site/src/app/[domain]/[language]/layout.tsx index dce6671fc..34ce3c8bb 100644 --- a/site/src/app/[domain]/[language]/layout.tsx +++ b/site/src/app/[domain]/[language]/layout.tsx @@ -1,6 +1,7 @@ import { SitePreviewProvider } from "@comet/cms-site"; import { IntlProvider } from "@src/util/IntlProvider"; import { loadMessages } from "@src/util/loadMessages"; +import { setNotFoundContext } from "@src/util/NotFoundContext"; import { getSiteConfigForDomain } from "@src/util/siteConfig"; import { SiteConfigProvider } from "@src/util/SiteConfigProvider"; import { draftMode } from "next/headers"; @@ -11,6 +12,7 @@ export default async function Page({ children, params: { domain, language } }: P if (!siteConfig.scope.languages.includes(language)) { language = "en"; } + setNotFoundContext({ domain, language }); const isDraftModeEnabled = draftMode().isEnabled; diff --git a/site/src/app/[domain]/[language]/not-found.tsx b/site/src/app/[domain]/[language]/not-found.tsx index 89b9ad758..54d860a5e 100644 --- a/site/src/app/[domain]/[language]/not-found.tsx +++ b/site/src/app/[domain]/[language]/not-found.tsx @@ -1,11 +1,28 @@ -import Link from "next/link"; +import NotFoundContent from "@src/documents/NotFound"; +import { IntlProvider } from "@src/util/IntlProvider"; +import { loadMessages } from "@src/util/loadMessages"; +import { getNotFoundContext } from "@src/util/NotFoundContext"; +import { getSiteConfigForDomain } from "@src/util/siteConfig"; +import { SiteConfigProvider } from "@src/util/SiteConfigProvider"; + +import Layout from "./[[...path]]/layout"; + +export default async function NotFound() { + const { domain, language } = getNotFoundContext() || { domain: "main", language: "en" }; + const messages = await loadMessages(language); -export default async function NotFound404() { return ( - + -

Page not found.

- Return Home + + + +
+ +
+
+
+
); diff --git a/site/src/app/not-found.tsx b/site/src/app/not-found.tsx deleted file mode 100644 index 65880db5d..000000000 --- a/site/src/app/not-found.tsx +++ /dev/null @@ -1,10 +0,0 @@ -// TODO https://github.com/vivid-planet/comet-starter/pull/285 -export default function NotFound() { - return ( - - -

Not found

- - - ); -} diff --git a/site/src/documents/NotFound.tsx b/site/src/documents/NotFound.tsx new file mode 100644 index 000000000..92e03f707 --- /dev/null +++ b/site/src/documents/NotFound.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { Typography } from "@src/common/components/Typography"; +import { PageLayout } from "@src/layout/PageLayout"; +import type { ContentScope } from "@src/site-configs"; +import Link from "next/link"; +import { FormattedMessage } from "react-intl"; +import styled from "styled-components"; + +export default function NotFoundContent({ scope }: { scope: ContentScope }) { + return ( + + + + + + + + + + + ); +} + +const PageLayoutContent = styled.div` + grid-column: 3 / -3; +`; + +const NotFoundTypography = styled(Typography)` + margin-top: ${({ theme }) => theme.spacing.S300}; + margin-bottom: ${({ theme }) => theme.spacing.S300}; +`; + +const HomeLink = styled(Link)` + text-decoration: none; + display: inline-block; + padding: ${({ theme }) => theme.spacing.S100} 0; + font-family: ${({ theme }) => theme.fontFamily}; + color: ${({ theme }) => theme.palette.text.primary}; + + &:hover { + color: ${({ theme }) => theme.palette.primary.main}; + } + + &.active { + text-decoration: underline ${({ theme }) => theme.palette.primary.main}; + text-underline-offset: 8px; + } +`; diff --git a/site/src/util/NotFoundContext.tsx b/site/src/util/NotFoundContext.tsx new file mode 100644 index 000000000..c5a79b3c8 --- /dev/null +++ b/site/src/util/NotFoundContext.tsx @@ -0,0 +1,25 @@ +import type { ContentScope } from "@src/site-configs"; +import { cache } from "react"; + +// https://github.com/vercel/next.js/discussions/43179#discussioncomment-11192893 +/** + * This is a workaround until Next.js adds support for true Server Context + * It works by using React `cache` to store the value for the lifetime of one rendering. + * Meaning it's available to all server components down the tree after it's set. + * Do not use this unless necessary. + * + * @warning This is a temporary workaround. + */ +function createServerContext(defaultValue: T): [() => T, (v: T) => void] { + const getRef = cache(() => ({ current: defaultValue })); + + const getValue = (): T => getRef().current; + + const setValue = (value: T) => { + getRef().current = value; + }; + + return [getValue, setValue]; +} + +export const [getNotFoundContext, setNotFoundContext] = createServerContext(null);