From 218f97a9b5a6a89fed88a4bd726369e02231a4ae Mon Sep 17 00:00:00 2001 From: Simon Vrachliotis Date: Fri, 19 Jul 2024 17:34:45 +1000 Subject: [PATCH] migrate to app router, with emotion working --- docs/app/(site)/blog/[post]/page-client.tsx | 58 ++++ docs/app/(site)/blog/[post]/page.tsx | 71 +++++ .../(site)/blog/page-client.tsx} | 99 ++---- docs/app/(site)/blog/page.tsx | 47 +++ .../(site)/branding/page-client.tsx} | 36 +-- docs/app/(site)/branding/page.tsx | 10 + .../app/(site)/docs/[...rest]/page-client.tsx | 33 ++ docs/app/(site)/docs/[...rest]/page.tsx | 54 ++++ .../docs/config/overview/page-client.tsx} | 18 +- docs/app/(site)/docs/config/overview/page.tsx | 10 + .../(site)/docs/examples/page-client.tsx} | 22 +- docs/app/(site)/docs/examples/page.tsx | 11 + .../document-field-demo/page-client.tsx} | 20 +- .../docs/guides/document-field-demo/page.tsx | 11 + .../docs/guides/overview/page-client.tsx} | 20 +- docs/app/(site)/docs/guides/overview/page.tsx | 11 + .../(site)/docs/page-client.tsx} | 43 ++- docs/app/(site)/docs/page.tsx | 10 + .../(site)/docs/walkthroughs/page-client.tsx} | 20 +- docs/app/(site)/docs/walkthroughs/page.tsx | 11 + .../ds.tsx => app/(site)/ds/page-client.tsx} | 46 ++- docs/app/(site)/ds/page.tsx | 10 + .../(site)/enterprise/page-client.tsx} | 59 ++-- docs/app/(site)/enterprise/page.tsx | 11 + .../for-content-management/page-client.tsx} | 50 ++- .../(site)/for-content-management/page.tsx | 11 + .../(site)/for-developers/page-client.tsx} | 68 ++-- docs/app/(site)/for-developers/page.tsx | 11 + .../(site)/for-organisations/page-client.tsx} | 46 ++- docs/app/(site)/for-organisations/page.tsx | 11 + docs/app/(site)/layout-client.tsx | 211 +++++++++++++ docs/app/(site)/layout.tsx | 110 +++++++ .../404.tsx => app/(site)/not-found.tsx} | 29 +- .../index.tsx => app/(site)/page-client.tsx} | 88 +++--- docs/app/(site)/page.tsx | 11 + .../(site)/updates/page-client.tsx} | 29 +- docs/app/(site)/updates/page.tsx | 10 + .../(site)/updates/roadmap/page-client.tsx} | 25 +- docs/app/(site)/updates/roadmap/page.tsx | 10 + .../(site)/why-keystone/page-client.tsx} | 76 +++-- docs/app/(site)/why-keystone/page.tsx | 11 + .../api/hero-image/route.tsx} | 25 +- docs/components/Announce.tsx | 6 +- docs/components/Breadcrumbs.tsx | 12 +- docs/components/ContactForm.tsx | 5 +- docs/components/Footer.tsx | 6 +- docs/components/Header.tsx | 27 +- docs/components/Markdoc.tsx | 4 +- docs/components/MobileMenu.tsx | 5 +- docs/components/Page.tsx | 295 +++++++----------- docs/components/RelatedContent.tsx | 5 +- docs/components/SkipLinks.tsx | 5 +- docs/components/Socials.tsx | 5 +- docs/components/SubscribeForm.tsx | 5 +- docs/components/Theme.tsx | 4 +- docs/components/ThemeToggle.tsx | 50 ++- docs/components/content/AdvancedReactCta.tsx | 5 +- docs/components/content/CodeBox.tsx | 5 +- docs/components/content/CodeWindow.tsx | 5 +- docs/components/content/CommunityCta.tsx | 5 +- docs/components/content/CustomerCard.tsx | 5 +- docs/components/content/EndCta.tsx | 6 +- docs/components/content/Intro.tsx | 5 +- docs/components/content/MWrapper.tsx | 5 +- docs/components/content/Pill.tsx | 5 +- docs/components/content/PillCta.tsx | 6 +- docs/components/content/Quote.tsx | 5 +- docs/components/content/Section.tsx | 5 +- docs/components/content/TweetBox.tsx | 5 +- docs/components/docs/ComingSoon.tsx | 4 +- docs/components/docs/CommunitySlackCTA.tsx | 5 +- docs/components/docs/CopyToClipboard.tsx | 4 +- docs/components/docs/DocsFooter.tsx | 5 +- docs/components/docs/DocumentEditorDemo.tsx | 6 +- docs/components/docs/ExamplesList.tsx | 5 +- docs/components/docs/GitHubExamplesCTA.tsx | 5 +- docs/components/docs/Heading.tsx | 7 +- docs/components/docs/Keystone5DocsCTA.tsx | 4 +- docs/components/docs/Navigation.tsx | 217 ++++++------- docs/components/docs/Sidebar.tsx | 4 +- docs/components/docs/TableOfContents.tsx | 7 +- docs/components/docs/WalkthroughsList.tsx | 5 +- docs/components/icons/ArrowR.tsx | 4 - docs/components/icons/Automated.tsx | 4 - docs/components/icons/Bulb.tsx | 3 +- docs/components/icons/Cli.tsx | 3 +- docs/components/icons/ClientLogos.tsx | 3 +- docs/components/icons/Close.tsx | 3 +- docs/components/icons/Code.tsx | 4 - docs/components/icons/Content.tsx | 4 - docs/components/icons/Copy.tsx | 3 +- docs/components/icons/Custom.tsx | 4 - docs/components/icons/DFATLogo.tsx | 3 +- docs/components/icons/DarkMode.tsx | 4 - docs/components/icons/Docs.tsx | 3 +- docs/components/icons/Download.tsx | 3 +- docs/components/icons/Edit.tsx | 3 +- docs/components/icons/Editor.tsx | 3 +- docs/components/icons/EnliticLogo.tsx | 3 +- docs/components/icons/Filter.tsx | 4 - docs/components/icons/FrontEndLogos.tsx | 4 +- docs/components/icons/GitHub.tsx | 3 +- docs/components/icons/GraphQl.tsx | 3 +- docs/components/icons/Hamburger.tsx | 3 +- docs/components/icons/Keystone.tsx | 4 - docs/components/icons/Lab.tsx | 3 +- docs/components/icons/LightMode.tsx | 3 +- docs/components/icons/Link.tsx | 3 +- docs/components/icons/Migration.tsx | 4 - docs/components/icons/Nextjs.tsx | 3 +- docs/components/icons/Nope.tsx | 3 +- docs/components/icons/Organization.tsx | 4 - docs/components/icons/PJohnsonLogo.tsx | 3 +- docs/components/icons/Postgres.tsx | 3 +- docs/components/icons/PrintBarLogo.tsx | 3 +- docs/components/icons/Prisma.tsx | 3 +- docs/components/icons/Profile.tsx | 3 +- docs/components/icons/Quote.tsx | 3 +- docs/components/icons/Relational.tsx | 4 - docs/components/icons/Relationship.tsx | 3 +- docs/components/icons/Roadmap.tsx | 4 - docs/components/icons/RugbyAuLogo.tsx | 3 +- docs/components/icons/Search.tsx | 4 +- docs/components/icons/SearchKeys.tsx | 4 +- docs/components/icons/Shield.tsx | 4 - docs/components/icons/Slack.tsx | 3 +- docs/components/icons/Thinkmill.tsx | 4 - docs/components/icons/Tick.tsx | 4 - docs/components/icons/Twitter.tsx | 3 +- docs/components/icons/Typescript.tsx | 4 - docs/components/icons/Updates.tsx | 4 - docs/components/icons/Video.tsx | 3 +- docs/components/icons/VocalLogo.tsx | 3 +- docs/components/icons/Watch.tsx | 3 - docs/components/icons/Welcome.tsx | 3 +- docs/components/icons/WestpacLogo.tsx | 3 +- docs/components/icons/WhyKeystone.tsx | 3 - docs/components/icons/YouTube.tsx | 3 +- docs/components/icons/util.tsx | 3 - docs/components/primitives/Alert.tsx | 6 +- docs/components/primitives/Badge.tsx | 5 +- docs/components/primitives/Button.tsx | 4 +- docs/components/primitives/Code.tsx | 26 +- docs/components/primitives/EditButton.tsx | 4 +- docs/components/primitives/Emoji.tsx | 8 +- docs/components/primitives/Field.tsx | 5 +- docs/components/primitives/GitHubButton.tsx | 7 +- docs/components/primitives/Gradient.tsx | 5 +- docs/components/primitives/Highlight.tsx | 5 +- docs/components/primitives/Loading.tsx | 8 +- docs/components/primitives/SearchField.tsx | 6 +- docs/components/primitives/Stack.tsx | 5 +- docs/components/primitives/Status.tsx | 5 +- docs/components/primitives/Type.tsx | 5 +- docs/components/primitives/Well.tsx | 5 +- docs/components/primitives/Wrapper.tsx | 5 +- docs/components/primitives/YouTubeEmbed.tsx | 4 - docs/content/docs/config/config.md | 3 +- .../docs/guides/custom-admin-ui-logo.md | 3 +- .../docs/guides/custom-admin-ui-pages.md | 3 +- docs/next-env.d.ts | 1 - docs/package.json | 2 +- docs/pages/_app.tsx | 108 ------- docs/pages/_document.tsx | 102 ------ docs/pages/blog/[post].tsx | 110 ------- docs/pages/docs/[...rest].tsx | 60 ---- docs/tsconfig.json | 2 +- 167 files changed, 1559 insertions(+), 1496 deletions(-) create mode 100644 docs/app/(site)/blog/[post]/page-client.tsx create mode 100644 docs/app/(site)/blog/[post]/page.tsx rename docs/{pages/blog/index.tsx => app/(site)/blog/page-client.tsx} (52%) create mode 100644 docs/app/(site)/blog/page.tsx rename docs/{pages/branding.tsx => app/(site)/branding/page-client.tsx} (85%) create mode 100644 docs/app/(site)/branding/page.tsx create mode 100644 docs/app/(site)/docs/[...rest]/page-client.tsx create mode 100644 docs/app/(site)/docs/[...rest]/page.tsx rename docs/{pages/docs/config/overview.tsx => app/(site)/docs/config/overview/page-client.tsx} (81%) create mode 100644 docs/app/(site)/docs/config/overview/page.tsx rename docs/{pages/docs/examples.tsx => app/(site)/docs/examples/page-client.tsx} (93%) create mode 100644 docs/app/(site)/docs/examples/page.tsx rename docs/{pages/docs/guides/document-field-demo.tsx => app/(site)/docs/guides/document-field-demo/page-client.tsx} (83%) create mode 100644 docs/app/(site)/docs/guides/document-field-demo/page.tsx rename docs/{pages/docs/guides/overview.tsx => app/(site)/docs/guides/overview/page-client.tsx} (88%) create mode 100644 docs/app/(site)/docs/guides/overview/page.tsx rename docs/{pages/docs/index.tsx => app/(site)/docs/page-client.tsx} (89%) create mode 100644 docs/app/(site)/docs/page.tsx rename docs/{pages/docs/walkthroughs/index.tsx => app/(site)/docs/walkthroughs/page-client.tsx} (85%) create mode 100644 docs/app/(site)/docs/walkthroughs/page.tsx rename docs/{pages/ds.tsx => app/(site)/ds/page-client.tsx} (94%) create mode 100644 docs/app/(site)/ds/page.tsx rename docs/{pages/enterprise.tsx => app/(site)/enterprise/page-client.tsx} (76%) create mode 100644 docs/app/(site)/enterprise/page.tsx rename docs/{pages/for-content-management.tsx => app/(site)/for-content-management/page-client.tsx} (90%) create mode 100644 docs/app/(site)/for-content-management/page.tsx rename docs/{pages/for-developers.tsx => app/(site)/for-developers/page-client.tsx} (90%) create mode 100644 docs/app/(site)/for-developers/page.tsx rename docs/{pages/for-organisations.tsx => app/(site)/for-organisations/page-client.tsx} (90%) create mode 100644 docs/app/(site)/for-organisations/page.tsx create mode 100644 docs/app/(site)/layout-client.tsx create mode 100644 docs/app/(site)/layout.tsx rename docs/{pages/404.tsx => app/(site)/not-found.tsx} (70%) rename docs/{pages/index.tsx => app/(site)/page-client.tsx} (92%) create mode 100644 docs/app/(site)/page.tsx rename docs/{pages/updates/index.tsx => app/(site)/updates/page-client.tsx} (98%) create mode 100644 docs/app/(site)/updates/page.tsx rename docs/{pages/updates/roadmap.tsx => app/(site)/updates/roadmap/page-client.tsx} (96%) create mode 100644 docs/app/(site)/updates/roadmap/page.tsx rename docs/{pages/why-keystone.tsx => app/(site)/why-keystone/page-client.tsx} (91%) create mode 100644 docs/app/(site)/why-keystone/page.tsx rename docs/{pages/api/hero-image.tsx => app/api/hero-image/route.tsx} (84%) delete mode 100644 docs/pages/_app.tsx delete mode 100644 docs/pages/_document.tsx delete mode 100644 docs/pages/blog/[post].tsx delete mode 100644 docs/pages/docs/[...rest].tsx diff --git a/docs/app/(site)/blog/[post]/page-client.tsx b/docs/app/(site)/blog/[post]/page-client.tsx new file mode 100644 index 00000000000..d7ac375bc1c --- /dev/null +++ b/docs/app/(site)/blog/[post]/page-client.tsx @@ -0,0 +1,58 @@ +/** @jsxImportSource @emotion/react */ + +'use client' + +import Link from 'next/link' +import { useParams } from 'next/navigation' +import { parse, format } from 'date-fns' + +import { extractHeadings, Markdoc } from '../../../../components/Markdoc' +import { BlogPage } from '../../../../components/Page' +import { Heading } from '../../../../components/docs/Heading' +import { Type } from '../../../../components/primitives/Type' +import { type BlogPost } from './page' + +export default function Page ({ post }: { post: BlogPost }) { + const params = useParams() + const headings = [{ id: 'title', depth: 1, label: post.title }, ...extractHeadings(post.content)] + + const publishedDate = post.publishDate + const parsedDate = parse(publishedDate, 'yyyy-M-d', new Date()) + const formattedDateStr = format(parsedDate, 'MMMM do, yyyy') + + return ( + + + {post.title} + + + + Published on {formattedDateStr} + {post.authorHandle ? ( + + {' '} + by{' '} + + {post.authorName} + + + ) : ( + by {post.authorName} + )} + + + {post.content.children.map((child, i) => ( + + ))} + + ) +} diff --git a/docs/app/(site)/blog/[post]/page.tsx b/docs/app/(site)/blog/[post]/page.tsx new file mode 100644 index 00000000000..ae1eb980304 --- /dev/null +++ b/docs/app/(site)/blog/[post]/page.tsx @@ -0,0 +1,71 @@ +import { type Tag, transform } from '@markdoc/markdoc' +import { notFound } from 'next/navigation' + +import { getOgAbsoluteUrl } from '../../../../lib/og-util' +import { reader } from '../../../../lib/keystatic-reader' +import { baseMarkdocConfig } from '../../../../markdoc/config' +import { type EntryWithResolvedLinkedFiles } from '@keystatic/core/reader' +import type keystaticConfig from '../../../../keystatic.config' +import PageClient from './page-client' +import { type Metadata } from 'next' + +export type BlogPost = NonNullable< + Omit< + EntryWithResolvedLinkedFiles<(typeof keystaticConfig)['collections']['posts']>, + 'content' + > & { + content: Tag + } +> + +export default async function Page ({ params }) { + const post = await reader.collections.posts.read(params!.post, { + resolveLinkedFiles: true, + }) + + if (!post) return notFound() + + return ( + + ) +} + +// Dynamic SEO page metadata +export async function generateMetadata ({ params }): Promise { + const post = await reader.collections.posts.read(params!.post) + + const title = post?.title ? `${post.title} - Keystone 6 Blog` : 'Keystone 6 Blog' + + let ogImageUrl = post?.metaImageUrl + if (!ogImageUrl) { + ogImageUrl = getOgAbsoluteUrl({ + title, + type: 'Blog', + }) + } + + return { + title, + description: post?.description, + openGraph: { + images: ogImageUrl, + }, + } +} + +// Static HTML page generation for each document page +export async function generateStaticPaths () { + const posts = await reader.collections.posts.list() + return { + paths: posts.map((post) => ({ params: { post } })), + fallback: false, + } +} diff --git a/docs/pages/blog/index.tsx b/docs/app/(site)/blog/page-client.tsx similarity index 52% rename from docs/pages/blog/index.tsx rename to docs/app/(site)/blog/page-client.tsx index c825d433b7e..503a2261ed9 100644 --- a/docs/pages/blog/index.tsx +++ b/docs/app/(site)/blog/page-client.tsx @@ -1,50 +1,20 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { type InferGetStaticPropsType, type GetStaticPropsResult } from 'next' +/** @jsxImportSource @emotion/react */ + +'use client' + import Link from 'next/link' -import { parse, format } from 'date-fns' -import { jsx } from '@emotion/react' -import { MWrapper } from '../../components/content/MWrapper' -import { Page } from '../../components/Page' -import { Type } from '../../components/primitives/Type' -import { Highlight } from '../../components/primitives/Highlight' -import { useMediaQuery } from '../../lib/media' -import { siteBaseUrl } from '../../lib/og-util' -import { reader } from '../../lib/keystatic-reader' -import { type Entry } from '@keystatic/core/reader' -import type keystaticConfig from '../../keystatic.config' +import { MWrapper } from '../../../components/content/MWrapper' +import { Page } from '../../../components/Page' +import { Type } from '../../../components/primitives/Type' +import { Highlight } from '../../../components/primitives/Highlight' +import { useMediaQuery } from '../../../lib/media' -const today = new Date() -export default function Docs (props: InferGetStaticPropsType) { +export default function Docs ({ posts }) { const mq = useMediaQuery() - // reverse chronologically sorted - const posts = props.posts - .map(p => { - const publishedDate = p.frontmatter.publishDate - const parsedDate = parse(publishedDate, 'yyyy-M-d', today) - const formattedDateStr = format(parsedDate, 'MMMM do, yyyy') - return { - ...p, - frontmatter: { ...p.frontmatter }, - parsedDate: parsedDate, - formattedDateStr: formattedDateStr, - } - }) - .sort((a, b) => { - if (a.frontmatter.publishDate === b.frontmatter.publishDate) { - return a.frontmatter.title.localeCompare(b.frontmatter.title) - } - return b.frontmatter.publishDate.localeCompare(a.frontmatter.publishDate) - }) - return ( - +
- {posts.map(post => { + {posts.map((post) => { return (
  • - - - - {post.frontmatter.title} - - + + + {post.frontmatter.title} + {post.frontmatter.description} @@ -157,20 +127,3 @@ export default function Docs (props: InferGetStaticPropsType ) } - -export async function getStaticProps (): Promise< - GetStaticPropsResult<{ - posts: { - slug: string - frontmatter: Omit, 'content'> - }[] - }> -> { - const keystaticPosts = await reader.collections.posts.all() - - const postMeta = keystaticPosts.map(post => ({ - slug: post.slug, - frontmatter: { ...post.entry, content: null }, - })) - return { props: { posts: postMeta } } -} diff --git a/docs/app/(site)/blog/page.tsx b/docs/app/(site)/blog/page.tsx new file mode 100644 index 00000000000..d28c66bd221 --- /dev/null +++ b/docs/app/(site)/blog/page.tsx @@ -0,0 +1,47 @@ +import { parse, format } from 'date-fns' + +import { reader } from '../../../lib/keystatic-reader' +import { siteBaseUrl } from '../../../lib/og-util' +import ClientPage from './page-client' +import { type Metadata } from 'next' + +const today = new Date() + +export const metadata: Metadata = { + title: 'Keystone Blog', + description: 'Blog posts from the team maintaining Keystone.', + openGraph: { + images: `${siteBaseUrl}/assets/blog/the-keystone-blog-cover.png` + } +} + +export default async function Docs () { + const keystaticPosts = await reader.collections.posts.all() + + const transformedPosts = keystaticPosts.map((post) => ({ + slug: post.slug, + frontmatter: { ...post.entry, content: null }, + })) + + // Reverse chronologically sorted + const sortedPosts = transformedPosts + .map((p) => { + const publishedDate = p.frontmatter.publishDate + const parsedDate = parse(publishedDate, 'yyyy-M-d', today) + const formattedDateStr = format(parsedDate, 'MMMM do, yyyy') + return { + ...p, + frontmatter: { ...p.frontmatter }, + parsedDate: parsedDate, + formattedDateStr: formattedDateStr, + } + }) + .sort((a, b) => { + if (a.frontmatter.publishDate === b.frontmatter.publishDate) { + return a.frontmatter.title.localeCompare(b.frontmatter.title) + } + return b.frontmatter.publishDate.localeCompare(a.frontmatter.publishDate) + }) + + return +} diff --git a/docs/pages/branding.tsx b/docs/app/(site)/branding/page-client.tsx similarity index 85% rename from docs/pages/branding.tsx rename to docs/app/(site)/branding/page-client.tsx index cd2b446ace7..8ee68425f55 100644 --- a/docs/pages/branding.tsx +++ b/docs/app/(site)/branding/page-client.tsx @@ -1,27 +1,27 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ -import { IntroWrapper, IntroHeading, IntroLead } from '../components/content/Intro' -import { Highlight } from '../components/primitives/Highlight' -import { MWrapper } from '../components/content/MWrapper' -import { Download } from '../components/icons/Download' -import { Keystone } from '../components/icons/Keystone' -import { Type } from '../components/primitives/Type' -import { Pill } from '../components/content/Pill' -import { Nope } from '../components/icons/Nope' -import { Tick } from '../components/icons/Tick' -import { useMediaQuery } from '../lib/media' -import { Page } from '../components/Page' -import { Alert } from '../components/primitives/Alert' -import { Button } from '../components/primitives/Button' -import { ArrowR } from '../components/icons/ArrowR' +'use client' + +import { IntroWrapper, IntroHeading, IntroLead } from '../../../components/content/Intro' +import { Highlight } from '../../../components/primitives/Highlight' +import { MWrapper } from '../../../components/content/MWrapper' +import { Download } from '../../../components/icons/Download' +import { Keystone } from '../../../components/icons/Keystone' +import { Type } from '../../../components/primitives/Type' +import { Pill } from '../../../components/content/Pill' +import { Nope } from '../../../components/icons/Nope' +import { Tick } from '../../../components/icons/Tick' +import { useMediaQuery } from '../../../lib/media' +import { Page } from '../../../components/Page' +import { Alert } from '../../../components/primitives/Alert' +import { Button } from '../../../components/primitives/Button' +import { ArrowR } from '../../../components/icons/ArrowR' export default function Brand () { const mq = useMediaQuery() return ( - + Branding diff --git a/docs/app/(site)/branding/page.tsx b/docs/app/(site)/branding/page.tsx new file mode 100644 index 00000000000..32e07479bb4 --- /dev/null +++ b/docs/app/(site)/branding/page.tsx @@ -0,0 +1,10 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'KeytoneJS Brand', + description: 'Keystones brand assets and guidelines', +} + +export default function Brand () { + return +} diff --git a/docs/app/(site)/docs/[...rest]/page-client.tsx b/docs/app/(site)/docs/[...rest]/page-client.tsx new file mode 100644 index 00000000000..1f8b251ec0d --- /dev/null +++ b/docs/app/(site)/docs/[...rest]/page-client.tsx @@ -0,0 +1,33 @@ +'use client' + +import { useParams } from 'next/navigation' + +import { type Document } from './page' + +import { extractHeadings, Markdoc } from '../../../../components/Markdoc' +import { DocsPage } from '../../../../components/Page' +import { Heading } from '../../../../components/docs/Heading' + +export default function PageClient ({ document }: { document: Document }) { + const params = useParams() + + const headings = [ + { id: 'title', depth: 1, label: document.title }, + ...extractHeadings(document.content), + ] + + return ( + + + {document.title} + + + {document.content.children.map((child, i) => ( + + ))} + + ) +} diff --git a/docs/app/(site)/docs/[...rest]/page.tsx b/docs/app/(site)/docs/[...rest]/page.tsx new file mode 100644 index 00000000000..ea5efb39653 --- /dev/null +++ b/docs/app/(site)/docs/[...rest]/page.tsx @@ -0,0 +1,54 @@ +import { notFound } from 'next/navigation' +import { type Tag, transform } from '@markdoc/markdoc' + +import { reader } from '../../../../lib/keystatic-reader' +import { baseMarkdocConfig } from '../../../../markdoc/config' +import PageClient from './page-client' +import { type EntryWithResolvedLinkedFiles } from '@keystatic/core/reader' +import type keystaticConfig from '../../../../keystatic.config' + +export type Document = NonNullable< + Pick< + EntryWithResolvedLinkedFiles<(typeof keystaticConfig)['collections']['docs']>, + 'title' | 'description' + > & { + content: Tag + } +> + +export default async function DocPage ({ params }) { + const doc = await reader.collections.docs.read(params!.rest.join('/'), { + resolveLinkedFiles: true, + }) + if (!doc) return notFound() + + return ( + + ) +} + +// Dynamic SEO page metadata +export async function generateMetadata ({ params }) { + const doc = await reader.collections.docs.read(params!.rest.join('/')) + return { + title: doc?.title ? `${doc.title} - Keystone 6 Documentation` : 'Keystone 6 Documentation', + description: doc?.description, + } +} + +// Static HTML page generation for each document page +export async function generateStaticPaths () { + const pages = await reader.collections.docs.list() + return { + paths: pages.map((page) => ({ params: { rest: page.split('/') } })), + fallback: false, + } +} diff --git a/docs/pages/docs/config/overview.tsx b/docs/app/(site)/docs/config/overview/page-client.tsx similarity index 81% rename from docs/pages/docs/config/overview.tsx rename to docs/app/(site)/docs/config/overview/page-client.tsx index 78606e7bee3..d4856220e3a 100644 --- a/docs/pages/docs/config/overview.tsx +++ b/docs/app/(site)/docs/config/overview/page-client.tsx @@ -1,12 +1,12 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ -import { CommunitySlackCTA } from '../../../components/docs/CommunitySlackCTA' -import { Type } from '../../../components/primitives/Type' -import { Well } from '../../../components/primitives/Well' -import { DocsPage } from '../../../components/Page' -import { useMediaQuery } from '../../../lib/media' +'use client' + +import { CommunitySlackCTA } from '../../../../../components/docs/CommunitySlackCTA' +import { Type } from '../../../../../components/primitives/Type' +import { Well } from '../../../../../components/primitives/Well' +import { DocsPage } from '../../../../../components/Page' +import { useMediaQuery } from '../../../../../lib/media' export default function Docs () { const mq = useMediaQuery() @@ -15,8 +15,6 @@ export default function Docs () { diff --git a/docs/app/(site)/docs/config/overview/page.tsx b/docs/app/(site)/docs/config/overview/page.tsx new file mode 100644 index 00000000000..0f759646ce3 --- /dev/null +++ b/docs/app/(site)/docs/config/overview/page.tsx @@ -0,0 +1,10 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'APIs', + description: 'Index for Keystone’s API reference docs.', +} + +export default function Docs () { + return +} diff --git a/docs/pages/docs/examples.tsx b/docs/app/(site)/docs/examples/page-client.tsx similarity index 93% rename from docs/pages/docs/examples.tsx rename to docs/app/(site)/docs/examples/page-client.tsx index e4b551c3f79..0a9b1b01069 100644 --- a/docs/pages/docs/examples.tsx +++ b/docs/app/(site)/docs/examples/page-client.tsx @@ -1,13 +1,13 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ -import { GitHubExamplesCTA } from '../../components/docs/GitHubExamplesCTA' -import { Type } from '../../components/primitives/Type' -import { DocsPage } from '../../components/Page' -import { Well } from '../../components/primitives/Well' -import { useMediaQuery } from '../../lib/media' -import { InlineCode } from '../../components/primitives/Code' +'use client' + +import { GitHubExamplesCTA } from '../../../../components/docs/GitHubExamplesCTA' +import { Type } from '../../../../components/primitives/Type' +import { DocsPage } from '../../../../components/Page' +import { Well } from '../../../../components/primitives/Well' +import { useMediaQuery } from '../../../../lib/media' +import { InlineCode } from '../../../../components/primitives/Code' export default function Docs () { const mq = useMediaQuery() @@ -16,10 +16,6 @@ export default function Docs () { diff --git a/docs/app/(site)/docs/examples/page.tsx b/docs/app/(site)/docs/examples/page.tsx new file mode 100644 index 00000000000..b0b2f013c50 --- /dev/null +++ b/docs/app/(site)/docs/examples/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Examples', + description: + 'A growing collection of projects you can run locally to learn more about Keystone’s many features. Use them as a reference for best practice, and springboard when adding features to your own project.', +} + +export default function Docs () { + return +} diff --git a/docs/pages/docs/guides/document-field-demo.tsx b/docs/app/(site)/docs/guides/document-field-demo/page-client.tsx similarity index 83% rename from docs/pages/docs/guides/document-field-demo.tsx rename to docs/app/(site)/docs/guides/document-field-demo/page-client.tsx index 71d1692b35d..cfa23dea49d 100644 --- a/docs/pages/docs/guides/document-field-demo.tsx +++ b/docs/app/(site)/docs/guides/document-field-demo/page-client.tsx @@ -1,23 +1,23 @@ + +'use client' + import React from 'react' -import { H1, H2 } from '../../../components/docs/Heading' -import { DocsPage } from '../../../components/Page' + +import { H1, H2 } from '../../../../../components/docs/Heading' +import { DocsPage } from '../../../../../components/Page' import { DocumentEditorDemo, DocumentFeaturesProvider, -} from '../../../components/docs/DocumentEditorDemo' -import { Well } from '../../../components/primitives/Well' -import { RelatedContent } from '../../../components/RelatedContent' -import { InlineCode } from '../../../components/primitives/Code' +} from '../../../../../components/docs/DocumentEditorDemo' +import { Well } from '../../../../../components/primitives/Well' +import { RelatedContent } from '../../../../../components/RelatedContent' +import { InlineCode } from '../../../../../components/primitives/Code' export default function DocumentFieldDemo () { const title = 'Document Fields Demo' return ( +} diff --git a/docs/pages/docs/guides/overview.tsx b/docs/app/(site)/docs/guides/overview/page-client.tsx similarity index 88% rename from docs/pages/docs/guides/overview.tsx rename to docs/app/(site)/docs/guides/overview/page-client.tsx index 0433d4906e0..e4e5ba8814a 100644 --- a/docs/pages/docs/guides/overview.tsx +++ b/docs/app/(site)/docs/guides/overview/page-client.tsx @@ -1,12 +1,12 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ -import { CommunitySlackCTA } from '../../../components/docs/CommunitySlackCTA' -import { Type } from '../../../components/primitives/Type' -import { Well } from '../../../components/primitives/Well' -import { DocsPage } from '../../../components/Page' -import { useMediaQuery } from '../../../lib/media' +'use client' + +import { CommunitySlackCTA } from '../../../../../components/docs/CommunitySlackCTA' +import { Type } from '../../../../../components/primitives/Type' +import { Well } from '../../../../../components/primitives/Well' +import { DocsPage } from '../../../../../components/Page' +import { useMediaQuery } from '../../../../../lib/media' export default function Docs () { const mq = useMediaQuery() @@ -15,10 +15,6 @@ export default function Docs () { diff --git a/docs/app/(site)/docs/guides/overview/page.tsx b/docs/app/(site)/docs/guides/overview/page.tsx new file mode 100644 index 00000000000..091b7dfb605 --- /dev/null +++ b/docs/app/(site)/docs/guides/overview/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Guides', + description: + 'Practical explanations of Keystone’s fundamental building blocks. Learn how to think about, and get the most out of Keystone’s many features.', +} + +export default function Docs () { + return +} diff --git a/docs/pages/docs/index.tsx b/docs/app/(site)/docs/page-client.tsx similarity index 89% rename from docs/pages/docs/index.tsx rename to docs/app/(site)/docs/page-client.tsx index 880a7280f0e..3149876e56c 100644 --- a/docs/pages/docs/index.tsx +++ b/docs/app/(site)/docs/page-client.tsx @@ -1,25 +1,26 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ + +'use client' + import Link from 'next/link' -import { CommunitySlackCTA } from '../../components/docs/CommunitySlackCTA' -import { Keystone5DocsCTA } from '../../components/docs/Keystone5DocsCTA' -import { Examples } from '../../components/docs/ExamplesList' -import { Walkthroughs } from '../../components/docs/WalkthroughsList' -import { Type } from '../../components/primitives/Type' -import { Well } from '../../components/primitives/Well' -import { DocsPage } from '../../components/Page' -import { useMediaQuery } from '../../lib/media' -import { CommunityCta } from '../../components/content/CommunityCta' -import { Content } from '../../components/icons/Content' -import { Code } from '../../components/icons/Code' -import { Bulb } from '../../components/icons/Bulb' -import { Video } from '../../components/icons/Video' -import { Organization } from '../../components/icons/Organization' -import { Alert } from '../../components/primitives/Alert' -import { Button } from '../../components/primitives/Button' -import { ArrowR } from '../../components/icons' +import { CommunitySlackCTA } from '../../../components/docs/CommunitySlackCTA' +import { Keystone5DocsCTA } from '../../../components/docs/Keystone5DocsCTA' +import { Examples } from '../../../components/docs/ExamplesList' +import { Walkthroughs } from '../../../components/docs/WalkthroughsList' +import { Type } from '../../../components/primitives/Type' +import { Well } from '../../../components/primitives/Well' +import { DocsPage } from '../../../components/Page' +import { useMediaQuery } from '../../../lib/media' +import { CommunityCta } from '../../../components/content/CommunityCta' +import { Content } from '../../../components/icons/Content' +import { Code } from '../../../components/icons/Code' +import { Bulb } from '../../../components/icons/Bulb' +import { Video } from '../../../components/icons/Video' +import { Organization } from '../../../components/icons/Organization' +import { Alert } from '../../../components/primitives/Alert' +import { Button } from '../../../components/primitives/Button' +import { ArrowR } from '../../../components/icons' export default function Docs () { const mq = useMediaQuery() @@ -28,8 +29,6 @@ export default function Docs () { diff --git a/docs/app/(site)/docs/page.tsx b/docs/app/(site)/docs/page.tsx new file mode 100644 index 00000000000..9d8f8d4e375 --- /dev/null +++ b/docs/app/(site)/docs/page.tsx @@ -0,0 +1,10 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Keystone Docs Home', + description: 'Developer docs for KeystoneJS: The superpowered headless CMS for developers.', +} + +export default function Docs () { + return +} diff --git a/docs/pages/docs/walkthroughs/index.tsx b/docs/app/(site)/docs/walkthroughs/page-client.tsx similarity index 85% rename from docs/pages/docs/walkthroughs/index.tsx rename to docs/app/(site)/docs/walkthroughs/page-client.tsx index 2312bb6efc8..1d7da3594de 100644 --- a/docs/pages/docs/walkthroughs/index.tsx +++ b/docs/app/(site)/docs/walkthroughs/page-client.tsx @@ -1,12 +1,12 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ -import { Type } from '../../../components/primitives/Type' -import { DocsPage } from '../../../components/Page' -import { Well } from '../../../components/primitives/Well' -import { useMediaQuery } from '../../../lib/media' -import { InlineCode } from '../../../components/primitives/Code' +'use client' + +import { Type } from '../../../../components/primitives/Type' +import { DocsPage } from '../../../../components/Page' +import { Well } from '../../../../components/primitives/Well' +import { useMediaQuery } from '../../../../lib/media' +import { InlineCode } from '../../../../components/primitives/Code' export function QuickStart () { const mq = useMediaQuery() @@ -74,10 +74,6 @@ export default function Docs () { diff --git a/docs/app/(site)/docs/walkthroughs/page.tsx b/docs/app/(site)/docs/walkthroughs/page.tsx new file mode 100644 index 00000000000..291536e6097 --- /dev/null +++ b/docs/app/(site)/docs/walkthroughs/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Walkthroughs', + description: + 'Explore tutorials with step-by-step instruction on building solutions with Keystone.', +} + +export default function Docs () { + return +} diff --git a/docs/pages/ds.tsx b/docs/app/(site)/ds/page-client.tsx similarity index 94% rename from docs/pages/ds.tsx rename to docs/app/(site)/ds/page-client.tsx index e631e7c4e7e..41ddd4e74a6 100644 --- a/docs/pages/ds.tsx +++ b/docs/app/(site)/ds/page-client.tsx @@ -1,24 +1,25 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ +/** @jsxImportSource @emotion/react */ + +'use client' + import { Fragment, useState } from 'react' -import { jsx } from '@emotion/react' -import { CodeWindow, WindowWrapper, WindowL, WindowR } from '../components/content/CodeWindow' -import { GitHubButton } from '../components/primitives/GitHubButton' -import { COLORS, TYPESCALE, TYPE, SPACE } from '../lib/TOKENS' -import { Highlight } from '../components/primitives/Highlight' -import { styleMap, Type } from '../components/primitives/Type' -import { InlineCode } from '../components/primitives/Code' -import { Status } from '../components/primitives/Status' -import { Button } from '../components/primitives/Button' -import { Alert } from '../components/primitives/Alert' -import { Badge } from '../components/primitives/Badge' -import { Emoji } from '../components/primitives/Emoji' -import { Stack } from '../components/primitives/Stack' -import { Field } from '../components/primitives/Field' -import { Well } from '../components/primitives/Well' -import * as allIcons from '../components/icons' -import { Page } from '../components/Page' +import { CodeWindow, WindowWrapper, WindowL, WindowR } from '../../../components/content/CodeWindow' +import { GitHubButton } from '../../../components/primitives/GitHubButton' +import { COLORS, TYPESCALE, TYPE, SPACE } from '../../../lib/TOKENS' +import { Highlight } from '../../../components/primitives/Highlight' +import { styleMap, Type } from '../../../components/primitives/Type' +import { InlineCode } from '../../../components/primitives/Code' +import { Status } from '../../../components/primitives/Status' +import { Button } from '../../../components/primitives/Button' +import { Alert } from '../../../components/primitives/Alert' +import { Badge } from '../../../components/primitives/Badge' +import { Emoji } from '../../../components/primitives/Emoji' +import { Stack } from '../../../components/primitives/Stack' +import { Field } from '../../../components/primitives/Field' +import { Well } from '../../../components/primitives/Well' +import * as allIcons from '../../../components/icons' +import { Page } from '../../../components/Page' const EXCEPT_ICONS = ['FrontEndLogos', 'ClientLogos'] @@ -96,10 +97,7 @@ export default function DS () { let firstGrad: string return ( - + Design System @@ -264,7 +262,7 @@ export default function DS () { Type - {(Object.keys(styleMap) as Array).map(style => ( + {(Object.keys(styleMap) as Array).map((style) => ( Type {style} diff --git a/docs/app/(site)/ds/page.tsx b/docs/app/(site)/ds/page.tsx new file mode 100644 index 00000000000..5991a0df853 --- /dev/null +++ b/docs/app/(site)/ds/page.tsx @@ -0,0 +1,10 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Design System Components and Tokens', + description: 'Design System Components & Tokens for the KeystoneJS website', +} + +export default function DS () { + return +} diff --git a/docs/pages/enterprise.tsx b/docs/app/(site)/enterprise/page-client.tsx similarity index 76% rename from docs/pages/enterprise.tsx rename to docs/app/(site)/enterprise/page-client.tsx index 9b29ae31bb3..5e851cf3547 100644 --- a/docs/pages/enterprise.tsx +++ b/docs/app/(site)/enterprise/page-client.tsx @@ -1,24 +1,25 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' -import { useMediaQuery } from '../lib/media' -import { Highlight } from '../components/primitives/Highlight' -import { MWrapper } from '../components/content/MWrapper' -import { Quote } from '../components/content/Quote' -import { Type } from '../components/primitives/Type' -import { Pill } from '../components/content/Pill' -import { Page } from '../components/Page' -import { ContactForm } from '../components/ContactForm' -import { CustomerCard } from '../components/content/CustomerCard' -import { VocalLogo } from '../components/icons/VocalLogo' -import { PJohnsonLogo } from '../components/icons/PJohnsonLogo' -import { DFATLogo } from '../components/icons/DFATLogo' -import { EnliticLogo } from '../components/icons/EnliticLogo' -import { RugbyAuLogo } from '../components/icons/RugbyAuLogo' -import { WestpacLogo } from '../components/icons/WestpacLogo' -import { PrintBarLogo } from '../components/icons/PrintBarLogo' -import { IntroHeading, IntroLead, IntroWrapper } from '../components/content/Intro' -import { Stack } from '../components/primitives/Stack' +/** @jsxImportSource @emotion/react */ + +'use client' + +import { useMediaQuery } from '../../../lib/media' +import { Highlight } from '../../../components/primitives/Highlight' +import { MWrapper } from '../../../components/content/MWrapper' +import { Quote } from '../../../components/content/Quote' +import { Type } from '../../../components/primitives/Type' +import { Pill } from '../../../components/content/Pill' +import { Page } from '../../../components/Page' +import { ContactForm } from '../../../components/ContactForm' +import { CustomerCard } from '../../../components/content/CustomerCard' +import { VocalLogo } from '../../../components/icons/VocalLogo' +import { PJohnsonLogo } from '../../../components/icons/PJohnsonLogo' +import { DFATLogo } from '../../../components/icons/DFATLogo' +import { EnliticLogo } from '../../../components/icons/EnliticLogo' +import { RugbyAuLogo } from '../../../components/icons/RugbyAuLogo' +import { WestpacLogo } from '../../../components/icons/WestpacLogo' +import { PrintBarLogo } from '../../../components/icons/PrintBarLogo' +import { IntroHeading, IntroLead, IntroWrapper } from '../../../components/content/Intro' +import { Stack } from '../../../components/primitives/Stack' const customers = [ { @@ -64,14 +65,8 @@ const customers = [ export default function ForOrganisations () { const mq = useMediaQuery() - return ( - + Keystone for Enterprise @@ -134,15 +129,15 @@ export default function ForOrganisations () {
  • {learnMoreHref ? ( - + {copy} - - + + ) : ( copy )} diff --git a/docs/app/(site)/enterprise/page.tsx b/docs/app/(site)/enterprise/page.tsx new file mode 100644 index 00000000000..81a361d2813 --- /dev/null +++ b/docs/app/(site)/enterprise/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'Keystone for Enterprise', + description: + 'Discover how Keystone’s Admin UI is a natural extension of how you work in code, and has the flexibility you need to enable content creatives.', +} + +export default function ForOrganisations () { + return +} diff --git a/docs/pages/for-content-management.tsx b/docs/app/(site)/for-content-management/page-client.tsx similarity index 90% rename from docs/pages/for-content-management.tsx rename to docs/app/(site)/for-content-management/page-client.tsx index a1168e6c668..ed2041f4fdb 100644 --- a/docs/pages/for-content-management.tsx +++ b/docs/app/(site)/for-content-management/page-client.tsx @@ -1,39 +1,35 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ + +'use client' + import Image from 'next/image' import Link from 'next/link' -import { useMediaQuery } from '../lib/media' -import { IntroWrapper, IntroHeading, IntroLead } from '../components/content/Intro' -import { Highlight } from '../components/primitives/Highlight' -import { MWrapper } from '../components/content/MWrapper' -import { Section, SideBySideSection } from '../components/content/Section' -import { Button } from '../components/primitives/Button' -import { Quote } from '../components/content/Quote' -import { Type } from '../components/primitives/Type' -import { ArrowR } from '../components/icons/ArrowR' -import { Pill } from '../components/content/Pill' -import { Tick } from '../components/icons/Tick' -import { Page } from '../components/Page' +import { useMediaQuery } from '../../../lib/media' +import { IntroWrapper, IntroHeading, IntroLead } from '../../../components/content/Intro' +import { Highlight } from '../../../components/primitives/Highlight' +import { MWrapper } from '../../../components/content/MWrapper' +import { Section, SideBySideSection } from '../../../components/content/Section' +import { Button } from '../../../components/primitives/Button' +import { Quote } from '../../../components/content/Quote' +import { Type } from '../../../components/primitives/Type' +import { ArrowR } from '../../../components/icons/ArrowR' +import { Pill } from '../../../components/content/Pill' +import { Tick } from '../../../components/icons/Tick' +import { Page } from '../../../components/Page' -import dsGeneration from '../public/assets/ds-generation.png' -import contentManagement1 from '../public/assets/content-management-1.png' -import contentManagement2 from '../public/assets/content-management-2.png' -import contentManagement3 from '../public/assets/content-management-3.png' -import contentManagement4 from '../public/assets/content-management-4.png' -import { EndCta } from '../components/content/EndCta' +import dsGeneration from '../../../public/assets/ds-generation.png' +import contentManagement1 from '../../../public/assets/content-management-1.png' +import contentManagement2 from '../../../public/assets/content-management-2.png' +import contentManagement3 from '../../../public/assets/content-management-3.png' +import contentManagement4 from '../../../public/assets/content-management-4.png' +import { EndCta } from '../../../components/content/EndCta' export default function ForOrganisations () { const mq = useMediaQuery() return ( - + Keystone for content management diff --git a/docs/app/(site)/for-content-management/page.tsx b/docs/app/(site)/for-content-management/page.tsx new file mode 100644 index 00000000000..29999fd0b78 --- /dev/null +++ b/docs/app/(site)/for-content-management/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'KeystoneJS for Content Management', + description: + 'Discover how Keystone’s Admin UI is a natural extension of how you work in code, and has the flexibility you need to enable content creatives.', +} + +export default function ForOrganisations () { + return +} diff --git a/docs/pages/for-developers.tsx b/docs/app/(site)/for-developers/page-client.tsx similarity index 90% rename from docs/pages/for-developers.tsx rename to docs/app/(site)/for-developers/page-client.tsx index 8e4c1724451..a68608d9e0f 100644 --- a/docs/pages/for-developers.tsx +++ b/docs/app/(site)/for-developers/page-client.tsx @@ -1,48 +1,44 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ + +'use client' + import Image from 'next/image' import Link from 'next/link' -import { useMediaQuery } from '../lib/media' -import { IntroWrapper, IntroHeading, IntroLead } from '../components/content/Intro' -import { CommunityCta } from '../components/content/CommunityCta' -import { FrontEndLogos } from '../components/icons/FrontEndLogos' -import { Highlight } from '../components/primitives/Highlight' -import { Relational } from '../components/icons/Relational' -import { TweetBox } from '../components/content/TweetBox' -import { MWrapper } from '../components/content/MWrapper' -import { Typescript } from '../components/icons/Typescript' -import { Section, SideBySideSection } from '../components/content/Section' -import { CodeBox } from '../components/content/CodeBox' -import { Button } from '../components/primitives/Button' -import { EndCta } from '../components/content/EndCta' -import { Postgres } from '../components/icons/Postgres' -import { Emoji } from '../components/primitives/Emoji' -import { GraphQl } from '../components/icons/GraphQl' -import { Type } from '../components/primitives/Type' -import { ArrowR } from '../components/icons/ArrowR' -import { Nextjs } from '../components/icons/Nextjs' -import { Shield } from '../components/icons/Shield' -import { Prisma } from '../components/icons/Prisma' -import { Pill } from '../components/content/Pill' -import { Tick } from '../components/icons/Tick' -import { Cli } from '../components/icons/Cli' -import { Page } from '../components/Page' +import { useMediaQuery } from '../../../lib/media' +import { IntroWrapper, IntroHeading, IntroLead } from '../../../components/content/Intro' +import { CommunityCta } from '../../../components/content/CommunityCta' +import { FrontEndLogos } from '../../../components/icons/FrontEndLogos' +import { Highlight } from '../../../components/primitives/Highlight' +import { Relational } from '../../../components/icons/Relational' +import { TweetBox } from '../../../components/content/TweetBox' +import { MWrapper } from '../../../components/content/MWrapper' +import { Typescript } from '../../../components/icons/Typescript' +import { Section, SideBySideSection } from '../../../components/content/Section' +import { CodeBox } from '../../../components/content/CodeBox' +import { Button } from '../../../components/primitives/Button' +import { EndCta } from '../../../components/content/EndCta' +import { Postgres } from '../../../components/icons/Postgres' +import { Emoji } from '../../../components/primitives/Emoji' +import { GraphQl } from '../../../components/icons/GraphQl' +import { Type } from '../../../components/primitives/Type' +import { ArrowR } from '../../../components/icons/ArrowR' +import { Nextjs } from '../../../components/icons/Nextjs' +import { Shield } from '../../../components/icons/Shield' +import { Prisma } from '../../../components/icons/Prisma' +import { Pill } from '../../../components/content/Pill' +import { Tick } from '../../../components/icons/Tick' +import { Cli } from '../../../components/icons/Cli' +import { Page } from '../../../components/Page' -import editorStorytelling from '../public/assets/editor-storytelling.png' -import richTextEditor from '../public/assets/rich-text-editor.png' +import editorStorytelling from '../../../public/assets/editor-storytelling.png' +import richTextEditor from '../../../public/assets/rich-text-editor.png' export default function ForDevelopers () { const mq = useMediaQuery() return ( - + Keystone for developers diff --git a/docs/app/(site)/for-developers/page.tsx b/docs/app/(site)/for-developers/page.tsx new file mode 100644 index 00000000000..4c03a164cad --- /dev/null +++ b/docs/app/(site)/for-developers/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'KeystoneJS for Developers', + description: + 'How the Keystone developer experience gives you the power to design APIs on the fly, build custom editing experiences, and deliver content to any frontend framework. All in version controllable code.', +} + +export default function ForDevelopers () { + return +} diff --git a/docs/pages/for-organisations.tsx b/docs/app/(site)/for-organisations/page-client.tsx similarity index 90% rename from docs/pages/for-organisations.tsx rename to docs/app/(site)/for-organisations/page-client.tsx index 198bfa580af..b332d8c8782 100644 --- a/docs/pages/for-organisations.tsx +++ b/docs/app/(site)/for-organisations/page-client.tsx @@ -1,37 +1,33 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import { jsx } from '@emotion/react' +/** @jsxImportSource @emotion/react */ + +'use client' + import Image from 'next/image' import Link from 'next/link' -import { useMediaQuery } from '../lib/media' -import { IntroWrapper, IntroHeading, IntroLead } from '../components/content/Intro' -import { Highlight } from '../components/primitives/Highlight' -import { ClientLogos } from '../components/icons/ClientLogos' -import { TweetBox } from '../components/content/TweetBox' -import { MWrapper } from '../components/content/MWrapper' -import { Section } from '../components/content/Section' -import { Thinkmill } from '../components/icons/Thinkmill' -import { Quote } from '../components/content/Quote' -import { Type } from '../components/primitives/Type' -import { Pill } from '../components/content/Pill' -import { Tick } from '../components/icons/Tick' -import { Page } from '../components/Page' +import { useMediaQuery } from '../../../lib/media' +import { IntroWrapper, IntroHeading, IntroLead } from '../../../components/content/Intro' +import { Highlight } from '../../../components/primitives/Highlight' +import { ClientLogos } from '../../../components/icons/ClientLogos' +import { TweetBox } from '../../../components/content/TweetBox' +import { MWrapper } from '../../../components/content/MWrapper' +import { Section } from '../../../components/content/Section' +import { Thinkmill } from '../../../components/icons/Thinkmill' +import { Quote } from '../../../components/content/Quote' +import { Type } from '../../../components/primitives/Type' +import { Pill } from '../../../components/content/Pill' +import { Tick } from '../../../components/icons/Tick' +import { Page } from '../../../components/Page' -import editor from '../public/assets/editor.png' -import dataIntegrity from '../public/assets/data-integrity.png' -import { EndCta } from '../components/content/EndCta' +import editor from '../../../public/assets/editor.png' +import dataIntegrity from '../../../public/assets/data-integrity.png' +import { EndCta } from '../../../components/content/EndCta' export default function ForOrganisations () { const mq = useMediaQuery() return ( - + Keystone for organisations diff --git a/docs/app/(site)/for-organisations/page.tsx b/docs/app/(site)/for-organisations/page.tsx new file mode 100644 index 00000000000..1a34b44c0e2 --- /dev/null +++ b/docs/app/(site)/for-organisations/page.tsx @@ -0,0 +1,11 @@ +import PageClient from './page-client' + +export const metadata = { + title: 'KeystoneJS for Organisations', + description: + 'Discover how Keystone’s flexibility lets organisations scale fast and sustainably with a backend that can be shaped to any business logic.', +} + +export default function ForOrganisations () { + return +} diff --git a/docs/app/(site)/layout-client.tsx b/docs/app/(site)/layout-client.tsx new file mode 100644 index 00000000000..39e4c8a0d64 --- /dev/null +++ b/docs/app/(site)/layout-client.tsx @@ -0,0 +1,211 @@ +/** @jsxImportSource @emotion/react */ + +'use client' + +import { CacheProvider } from '@emotion/react' +import { useServerInsertedHTML } from 'next/navigation' +import { useContext, useEffect, useMemo, useState } from 'react' +import createCache from '@emotion/cache' +import Script from 'next/script' +import { Global, css } from '@emotion/react' + +import { proseStyles } from '../../lib/prose-lite' +import { Theme } from '../../components/Theme' +import { NavContextProvider } from '../../components/docs/Navigation' +import { SkipLinks } from '../../components/SkipLinks' +import { createContext } from 'react' + +function getTheme () { + const isSystemColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)').matches + const localStorageTheme = localStorage.theme + if ((!localStorageTheme && isSystemColorSchemeDark) || localStorageTheme === 'dark') { + return 'dark' + } + return 'light' +} + +const ThemeContext = createContext({ + theme: 'light' as 'dark' | 'light', + setTheme: (theme: 'dark' | 'light') => {}, +}) + +export function useThemeContext () { + return useContext(ThemeContext) +} + +export function Html (props: { children: React.ReactNode}) { + const [theme, setTheme] = useState<'light' | 'dark'>(() => { + if (typeof window === 'undefined') return 'light' + return getTheme() + }) + useEffect(() => { + const listener = () => { + setTheme(getTheme()) + } + const match = window.matchMedia('(prefers-color-scheme: dark)') + match.addEventListener('change', listener) + return () => { + match.removeEventListener('change', listener) + } + }, []) + const context = useMemo(() => ({ + theme, + setTheme (theme:'dark' | 'light') { + setTheme((theme) => (theme === 'dark' ? 'light' : 'dark')) + localStorage.setItem('theme', theme) + } + }), [theme, setTheme]) + return {props.children} +} + +export default function RootLayoutClient ({ children }: { children: React.ReactNode }) { + const [{ cache, flush }] = useState(() => { + const cache = createCache({ key: 'my' }) + cache.compat = true + const prevInsert = cache.insert + let inserted: string[] = [] + cache.insert = (...args) => { + const serialized = args[1] + if (cache.inserted[serialized.name] === undefined) { + inserted.push(serialized.name) + } + return prevInsert(...args) + } + const flush = () => { + const prevInserted = inserted + inserted = [] + return prevInserted + } + return { cache, flush } + }) + + useServerInsertedHTML(() => { + const names = flush() + if (names.length === 0) return null + let styles = '' + for (const name of names) { + styles += cache.inserted[name] + } + return ( +