diff --git a/.changeset/add-isnullable-multiselect.md b/.changeset/add-isnullable-multiselect.md deleted file mode 100644 index edf3088e6da..00000000000 --- a/.changeset/add-isnullable-multiselect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': minor ---- - -Add `db.isNullable` support for multiselect field type, defaults to false diff --git a/.changeset/config.json b/.changeset/config.json index a96ace8c24c..24654475a0b 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -5,6 +5,9 @@ "baseBranch": "main", "linked": [], "access": "public", + "privatePackages": { + "version": false + }, "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { "onlyUpdatePeerDependentsWhenOutOfRange": true } diff --git a/.changeset/contributors.json b/.changeset/contributors.json index 895f18cd532..665363c39a3 100644 --- a/.changeset/contributors.json +++ b/.changeset/contributors.json @@ -38,6 +38,7 @@ "dcousens", "dependabot", "dependabot[bot]", + "direisc", "dominikwilkowski", "duidae", "emmatown", diff --git a/.changeset/fix-bigint-validation.md b/.changeset/fix-bigint-validation.md deleted file mode 100644 index 2c49d9e94d8..00000000000 --- a/.changeset/fix-bigint-validation.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': patch ---- - -Fix bigInt field type to throw if `defaultValue: { kind: 'autoincrement' }` and `validation.isRequired` is set diff --git a/.changeset/fix-hide-ui.md b/.changeset/fix-hide-ui.md deleted file mode 100644 index a0fa2c69c6f..00000000000 --- a/.changeset/fix-hide-ui.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': patch ---- - -Fix `list.ui.hide*` defaulting to false when GraphQL is omitted diff --git a/.changeset/fix-keystone-prisma.md b/.changeset/fix-keystone-prisma.md deleted file mode 100644 index 4b71b10fec5..00000000000 --- a/.changeset/fix-keystone-prisma.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': patch ---- - -Fix `keystone prisma ...` not returning the same error code as the Prisma engine diff --git a/.changeset/fix-uuid-rel.md b/.changeset/fix-uuid-rel.md deleted file mode 100644 index dc50719a017..00000000000 --- a/.changeset/fix-uuid-rel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': patch ---- - -Fix malformed uuid's from breaking relationship filters when using POSTGRESQL diff --git a/.changeset/light-lamps-eat.md b/.changeset/light-lamps-eat.md deleted file mode 100644 index 208bfb90424..00000000000 --- a/.changeset/light-lamps-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/core': minor ---- - -Add exports for internal AdminUI pagination components `Pagination`, `PaginationLabel` and `usePaginationParams` for use in custom pages diff --git a/.changeset/split-document-field.md b/.changeset/split-document-field.md deleted file mode 100644 index 19265a633ed..00000000000 --- a/.changeset/split-document-field.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@keystone-6/fields-document': minor ---- - -Fix `@keystone-6/fields-document` package breaking when compiling in SSR environments (#8717) diff --git a/.changeset/update-field-hooks.md b/.changeset/update-field-hooks.md deleted file mode 100644 index b0ea3bd7d5f..00000000000 --- a/.changeset/update-field-hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@keystone-6/core": patch ---- - -Update built-in fields to use newer validate hook syntax diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000000..6c2b9be4c4f --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +link-workspace-packages=true +prefer-workspace-packages=true diff --git a/LICENSE b/LICENSE index 2762e648976..8f0e5cd3917 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Thinkmill Labs Pty Ltd +Copyright (c) 2024 Thinkmill Labs Pty Ltd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8e401a59fdd..54b63a1a1e9 100644 --- a/README.md +++ b/README.md @@ -87,4 +87,4 @@ For vulnerability reporting, please refer to our [security policy](/SECURITY.md) Thinkmill -Copyright (c) 2023 [Thinkmill Labs](https://www.thinkmill.com.au/labs?utm_campaign=keystone-github) Pty Ltd. Licensed under the MIT License. +Copyright (c) 2024 [Thinkmill Labs](https://www.thinkmill.com.au/labs?utm_campaign=keystone-github) Pty Ltd. Licensed under the MIT License. diff --git a/design-system/packages/button/package.json b/design-system/packages/button/package.json index 4566143100b..2522f425f13 100644 --- a/design-system/packages/button/package.json +++ b/design-system/packages/button/package.json @@ -12,14 +12,14 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:" + "@types/react": "^18.3.3" }, "dependencies": { "@babel/runtime": "^7.24.7", "@keystone-ui/core": "workspace:^", "@keystone-ui/icons": "workspace:^", "@keystone-ui/loading": "workspace:^", - "react": "catalog:" + "react": "^18.3.1" }, "repository": "https://github.com/keystonejs/keystone/tree/main/design-system/packages/button" } diff --git a/design-system/packages/core/package.json b/design-system/packages/core/package.json index e4e0d5d09eb..5fb189129e1 100644 --- a/design-system/packages/core/package.json +++ b/design-system/packages/core/package.json @@ -12,13 +12,13 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:", - "react": "catalog:", - "react-dom": "catalog:" + "@types/react": "^18.3.3", + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "peerDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/design-system/packages/fields/package.json b/design-system/packages/fields/package.json index 5fe7a755d5f..a4a6a86284b 100644 --- a/design-system/packages/fields/package.json +++ b/design-system/packages/fields/package.json @@ -12,7 +12,7 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:" + "@types/react": "^18.3.3" }, "dependencies": { "@babel/runtime": "^7.24.7", @@ -20,9 +20,9 @@ "@keystone-ui/icons": "workspace:^", "@keystone-ui/popover": "workspace:^", "date-fns": "^3.0.0", - "react": "catalog:", + "react": "^18.3.1", "react-day-picker": "^8.0.4", - "react-dom": "catalog:", + "react-dom": "^18.3.1", "react-focus-lock": "^2.7.1", "react-select": "^5.2.1" }, diff --git a/design-system/packages/icons/package.json b/design-system/packages/icons/package.json index e96ee372636..3d200806747 100644 --- a/design-system/packages/icons/package.json +++ b/design-system/packages/icons/package.json @@ -1162,10 +1162,10 @@ "@svgr/core": "^8.0.0", "@svgr/plugin-jsx": "^8.0.0", "@svgr/plugin-svgo": "^8.0.0", - "@types/react": "catalog:", + "@types/react": "^18.3.3", "feather-icons": "^4.28.0", "globby": "^14.0.0", - "react": "catalog:", + "react": "^18.3.1", "to-pascal-case": "^1.0.0" }, "dependencies": { @@ -1173,7 +1173,7 @@ "@keystone-ui/core": "workspace:^" }, "peerDependencies": { - "react": "catalog:" + "react": "^18.3.1" }, "preconstruct": { "entrypoints": [ diff --git a/design-system/packages/loading/package.json b/design-system/packages/loading/package.json index 9cd72e5df7a..161bef8e560 100644 --- a/design-system/packages/loading/package.json +++ b/design-system/packages/loading/package.json @@ -12,12 +12,12 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:" + "@types/react": "^18.3.3" }, "dependencies": { "@babel/runtime": "^7.24.7", "@keystone-ui/core": "workspace:^", - "react": "catalog:" + "react": "^18.3.1" }, "repository": "https://github.com/keystonejs/keystone/tree/main/design-system/packages/loading" } diff --git a/design-system/packages/modals/package.json b/design-system/packages/modals/package.json index 7ad7a70e4f4..4c171bee16b 100644 --- a/design-system/packages/modals/package.json +++ b/design-system/packages/modals/package.json @@ -12,15 +12,15 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:", + "@types/react": "^18.3.3", "@types/react-transition-group": "4.4.10" }, "dependencies": { "@babel/runtime": "^7.24.7", "@keystone-ui/button": "workspace:^", "@keystone-ui/core": "workspace:^", - "react": "catalog:", - "react-dom": "catalog:", + "react": "^18.3.1", + "react-dom": "^18.3.1", "react-focus-lock": "^2.7.1", "react-remove-scroll": "^2.4.3", "react-transition-group": "^4.4.2" diff --git a/design-system/packages/notice/package.json b/design-system/packages/notice/package.json index a222ed7e3c8..bb87940b905 100644 --- a/design-system/packages/notice/package.json +++ b/design-system/packages/notice/package.json @@ -12,14 +12,14 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:" + "@types/react": "^18.3.3" }, "dependencies": { "@babel/runtime": "^7.24.7", "@keystone-ui/button": "workspace:^", "@keystone-ui/core": "workspace:^", "@keystone-ui/icons": "workspace:^", - "react": "catalog:" + "react": "^18.3.1" }, "repository": "https://github.com/keystonejs/keystone/tree/main/design-system/packages/notice" } diff --git a/design-system/packages/options/package.json b/design-system/packages/options/package.json index 38022dd136d..38e4ec075b4 100644 --- a/design-system/packages/options/package.json +++ b/design-system/packages/options/package.json @@ -12,12 +12,12 @@ "./package.json": "./package.json" }, "peerDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "devDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/design-system/packages/pill/package.json b/design-system/packages/pill/package.json index a6a41a74e62..4cfa2e947f7 100644 --- a/design-system/packages/pill/package.json +++ b/design-system/packages/pill/package.json @@ -12,10 +12,10 @@ "./package.json": "./package.json" }, "peerDependencies": { - "react": "catalog:" + "react": "^18.3.1" }, "devDependencies": { - "react": "catalog:" + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/design-system/packages/popover/package.json b/design-system/packages/popover/package.json index 2dcf0d766b6..a7164d3d0b6 100644 --- a/design-system/packages/popover/package.json +++ b/design-system/packages/popover/package.json @@ -12,12 +12,12 @@ "./package.json": "./package.json" }, "peerDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "devDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/design-system/packages/segmented-control/package.json b/design-system/packages/segmented-control/package.json index 40c2182a763..12fdfb60c44 100644 --- a/design-system/packages/segmented-control/package.json +++ b/design-system/packages/segmented-control/package.json @@ -12,15 +12,15 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:", - "react": "catalog:" + "@types/react": "^18.3.3", + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", "@keystone-ui/core": "workspace:^" }, "peerDependencies": { - "react": "catalog:" + "react": "^18.3.1" }, "repository": "https://github.com/keystonejs/keystone/tree/main/design-system/packages/segmented-control" } diff --git a/design-system/packages/toast/package.json b/design-system/packages/toast/package.json index 6c76869eca8..76f139fceb0 100644 --- a/design-system/packages/toast/package.json +++ b/design-system/packages/toast/package.json @@ -12,8 +12,8 @@ "./package.json": "./package.json" }, "devDependencies": { - "@types/react": "catalog:", - "react": "catalog:" + "@types/react": "^18.3.3", + "react": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", @@ -21,7 +21,7 @@ "@keystone-ui/icons": "workspace:^" }, "peerDependencies": { - "react": "catalog:" + "react": "^18.3.1" }, "repository": "https://github.com/keystonejs/keystone/tree/main/design-system/packages/toast" } diff --git a/design-system/packages/tooltip/package.json b/design-system/packages/tooltip/package.json index e29f3351f94..e4bc853c3c5 100644 --- a/design-system/packages/tooltip/package.json +++ b/design-system/packages/tooltip/package.json @@ -12,12 +12,12 @@ "./package.json": "./package.json" }, "peerDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "devDependencies": { - "react": "catalog:", - "react-dom": "catalog:" + "react": "^18.3.1", + "react-dom": "^18.3.1" }, "dependencies": { "@babel/runtime": "^7.24.7", diff --git a/design-system/website/components/Navigation.tsx b/design-system/website/components/Navigation.tsx index f93a7e9ea14..c8e52158799 100644 --- a/design-system/website/components/Navigation.tsx +++ b/design-system/website/components/Navigation.tsx @@ -4,7 +4,7 @@ import { Fragment, type ReactNode } from 'react' import { jsx, useTheme } from '@keystone-ui/core' import Link from 'next/link' -import { useRouter } from 'next/router' +import { usePathname } from 'next/navigation' const Brand = () => { const { palette } = useTheme() @@ -37,8 +37,8 @@ const Section = ({ label, children }: SectionProps) => { type NavItemProps = { href: string, children: ReactNode } const NavItem = ({ href, children }: NavItemProps) => { const { palette, radii, spacing } = useTheme() - const router = useRouter() - const isSelected = router.pathname === href + const pathname = usePathname() + const isSelected = pathname === href 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..ac22aa6516f --- /dev/null +++ b/docs/app/(site)/blog/[post]/page.tsx @@ -0,0 +1,68 @@ +import { type Tag, transform } from '@markdoc/markdoc' +import { notFound } from 'next/navigation' + +import { getOgAbsoluteUrl } from '../../../../lib/og-util' +import { reader } from '../../../../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 generateStaticParams () { + const posts = await reader.collections.posts.list() + return posts.map((post) => ({ post })) +} 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..9ed12ec9a1f --- /dev/null +++ b/docs/app/(site)/blog/page.tsx @@ -0,0 +1,46 @@ +import { parse, format } from 'date-fns' + +import { reader } from '../../../keystatic/reader' +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: '/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..c5531b2b94c --- /dev/null +++ b/docs/app/(site)/docs/[...rest]/page-client.tsx @@ -0,0 +1,21 @@ +'use client' + +import { type Document } from './page' + +import { Markdoc } from '../../../../components/Markdoc' + +import { Heading } from '../../../../components/docs/Heading' + +export default function PageClient ({ document }: { document: Document }) { + 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..e8a29b42bb8 --- /dev/null +++ b/docs/app/(site)/docs/[...rest]/page.tsx @@ -0,0 +1,57 @@ +import { notFound } from 'next/navigation' +import { type Tag, transform } from '@markdoc/markdoc' + +import { reader } from '../../../../keystatic/reader' +import { baseMarkdocConfig } from '../../../../markdoc/config' +import { extractHeadings } from '../../../../markdoc/headings' +import PageClient from './page-client' +import { type EntryWithResolvedLinkedFiles } from '@keystatic/core/reader' +import type keystaticConfig from '../../../../keystatic.config' +import { DocsLayout } from '../../../../components/docs/DocsLayout' + +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() + + const transformedDoc: Document = { + ...doc, + content: transform(doc.content.node, baseMarkdocConfig) as Tag, + } + + const headings = [ + { id: 'title', depth: 1, label: transformedDoc.title }, + ...extractHeadings(transformedDoc.content), + ] + + 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 generateStaticParams () { + const pages = await reader.collections.docs.list() + return pages.map((page) => ({ rest: page.split('/') })) +} diff --git a/docs/pages/docs/config/overview.tsx b/docs/app/(site)/docs/config/overview/page-client.tsx similarity index 76% rename from docs/pages/docs/config/overview.tsx rename to docs/app/(site)/docs/config/overview/page-client.tsx index 78606e7bee3..293146cdd57 100644 --- a/docs/pages/docs/config/overview.tsx +++ b/docs/app/(site)/docs/config/overview/page-client.tsx @@ -1,25 +1,17 @@ -/** @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 { useMediaQuery } from '../../../../../lib/media' export default function Docs () { const mq = useMediaQuery() return ( - + <> Configuration Overview @@ -62,6 +54,6 @@ export default function Docs () { and one-time authentication tokens. - + ) } 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..45367d9b252 --- /dev/null +++ b/docs/app/(site)/docs/config/overview/page.tsx @@ -0,0 +1,15 @@ +import { DocsLayout } from '../../../../../components/docs/DocsLayout' +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/app/(site)/docs/examples/page-client.tsx b/docs/app/(site)/docs/examples/page-client.tsx new file mode 100644 index 00000000000..6c01dccecca --- /dev/null +++ b/docs/app/(site)/docs/examples/page-client.tsx @@ -0,0 +1,97 @@ +/** @jsxImportSource @emotion/react */ + +'use client' + +import { type Tag } from '@markdoc/markdoc' + +import { type GroupedExamples } from './page' +import { GitHubExamplesCTA } from '../../../../components/docs/GitHubExamplesCTA' +import { Type } from '../../../../components/primitives/Type' +import { FeaturedCard, SplitCardContainer } from '../../../../components/docs/FeaturedCard' +import { useMediaQuery } from '../../../../lib/media' + +export default function Docs ({ + standaloneExamples, + endToEndExamples, + deploymentExamples, +}: GroupedExamples) { + return ( + <> + + Examples + + + + A growing collection of projects you can run locally to learn more about Keystone’s + capabilities. Each example includes documentation explaining the how and why. Use them as a + reference for best practice, and a jumping off point when adding features to your own + Keystone project. + + + + + + Standalone Examples + + + + Standalone examples demonstrate how a particular feature works or how to solve a problem + with Keystone. + + + + {standaloneExamples.map((example) => ( + + ))} + + + + End-to-End Examples + + + + End to end examples demonstrate how a feature works or how to solve a problem with an + independent frontend application and a Keystone server. + + + + {endToEndExamples.map((example) => ( + + ))} + + + + Deployment Examples + + + + Examples with all the code and documentation you need to get a Keystone project hosted on + the web. You can find them in the{' '} + Keystone Github Organisation. + + + + {deploymentExamples.map((example) => ( + + ))} + + + ) +} diff --git a/docs/app/(site)/docs/examples/page.tsx b/docs/app/(site)/docs/examples/page.tsx new file mode 100644 index 00000000000..714e9dac62a --- /dev/null +++ b/docs/app/(site)/docs/examples/page.tsx @@ -0,0 +1,44 @@ +import { transform } from '@markdoc/markdoc' +import { DocsLayout } from '../../../../components/docs/DocsLayout' +import { reader } from '../../../../keystatic/reader' +import PageClient from './page-client' +import { baseMarkdocConfig } from '../../../../markdoc/config' + +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 type GroupedExamples = Awaited> + +async function getGroupedExamples () { + const examples = await reader.collections.examples.all({resolveLinkedFiles: true}) + const transformedExamples = await Promise.all(examples.map(async example => { + return { + ...example, + entry : { + ...example.entry, + description: transform(example.entry.description.node, baseMarkdocConfig) + } + } + })) + + const standaloneExamples = transformedExamples.filter(example => example.entry.kind === 'standalone') + const endToEndExamples = transformedExamples.filter(example => example.entry.kind === 'end-to-end') + const deploymentExamples = transformedExamples.filter(example => example.entry.kind === 'deployment') + + return { + standaloneExamples, + endToEndExamples, + deploymentExamples + } +} + +export default async function Docs () { + const pageData = await getGroupedExamples() + 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 70% 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..a4069d16453 100644 --- a/docs/pages/docs/guides/document-field-demo.tsx +++ b/docs/app/(site)/docs/guides/document-field-demo/page-client.tsx @@ -1,42 +1,22 @@ + +'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 { 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 ( - + <>

    {title}

    @@ -85,6 +65,6 @@ export default function DocumentFieldDemo () {
    -
    + ) } diff --git a/docs/app/(site)/docs/guides/document-field-demo/page.tsx b/docs/app/(site)/docs/guides/document-field-demo/page.tsx new file mode 100644 index 00000000000..953bb958c8d --- /dev/null +++ b/docs/app/(site)/docs/guides/document-field-demo/page.tsx @@ -0,0 +1,36 @@ +import { DocsLayout } from '../../../../../components/docs/DocsLayout' +import PageClient from './page-client' + +export const metadata = { + title: 'Document Fields Demo', + description: + 'Try Keystone’s powerful new Document field. Experiment with its config settings in real time to shape custom editing experiences.', +} + +export default function DocumentFieldDemo () { + return ( + + + + ) +} diff --git a/docs/pages/docs/guides/overview.tsx b/docs/app/(site)/docs/guides/overview/page-client.tsx similarity index 86% rename from docs/pages/docs/guides/overview.tsx rename to docs/app/(site)/docs/guides/overview/page-client.tsx index 0433d4906e0..fff1a218e37 100644 --- a/docs/pages/docs/guides/overview.tsx +++ b/docs/app/(site)/docs/guides/overview/page-client.tsx @@ -1,27 +1,17 @@ -/** @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 { useMediaQuery } from '../../../../../lib/media' export default function Docs () { const mq = useMediaQuery() return ( - + <> Keystone Guides @@ -113,6 +103,6 @@ export default function Docs () { Learn how to add your own custom pages to Keystone’s Admin UI. - + ) } 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..a8c53f83910 --- /dev/null +++ b/docs/app/(site)/docs/guides/overview/page.tsx @@ -0,0 +1,16 @@ +import { DocsLayout } from '../../../../../components/docs/DocsLayout' +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/app/(site)/docs/page-client.tsx b/docs/app/(site)/docs/page-client.tsx new file mode 100644 index 00000000000..48ffe26f1a2 --- /dev/null +++ b/docs/app/(site)/docs/page-client.tsx @@ -0,0 +1,43 @@ +/** @jsxImportSource @emotion/react */ + +'use client' + +import { CommunitySlackCTA } from '../../../components/docs/CommunitySlackCTA' +import { Keystone5DocsCTA } from '../../../components/docs/Keystone5DocsCTA' +import { Type } from '../../../components/primitives/Type' +import { CommunityCta } from '../../../components/content/CommunityCta' +import { Alert } from '../../../components/primitives/Alert' +import { Button } from '../../../components/primitives/Button' +import { ArrowR } from '../../../components/icons' +import { KeystoneExperience } from '../../../components/docs/KeystoneExperience' + +export default function DocsPageClient ({ featuredExamples, featuredDocs }) { + + return ( + <> + + Developer Docs + + + + + + + Looking for enterprise-grade consulting & support? + + + + + {featuredDocs} + {featuredExamples} + + + ) +} diff --git a/docs/app/(site)/docs/page.tsx b/docs/app/(site)/docs/page.tsx new file mode 100644 index 00000000000..a81481a282a --- /dev/null +++ b/docs/app/(site)/docs/page.tsx @@ -0,0 +1,21 @@ +import PageClient from './page-client' +import { FeaturedExamples } from '../../../components/docs/featured-examples' +import { FeaturedDocs } from '../../../components/docs/featured-docs' + +import { DocsLayout } from '../../../components/docs/DocsLayout' + +export const metadata = { + title: 'Keystone Docs Home', + description: 'Developer docs for KeystoneJS: The superpowered headless CMS for developers.', +} + +export default function Docs () { + return ( + + } + featuredDocs={} + /> + + ) +} diff --git a/docs/app/(site)/docs/walkthroughs/page-client.tsx b/docs/app/(site)/docs/walkthroughs/page-client.tsx new file mode 100644 index 00000000000..170af891063 --- /dev/null +++ b/docs/app/(site)/docs/walkthroughs/page-client.tsx @@ -0,0 +1,67 @@ +/** @jsxImportSource @emotion/react */ + +'use client' + +import { Type } from '../../../../components/primitives/Type' +import { type FeaturedDocsMap } from '../../../../keystatic/get-featured-docs-map' +import { + FeaturedCard, + FullWidthCardContainer, + SplitCardContainer, +} from '../../../../components/docs/FeaturedCard' + +export default function Docs ({ + quickstart, + walkthroughs, +}: { + quickstart: NonNullable[number]['items'][number] + walkthroughs: NonNullable[number]['items'] +}) { + return ( + <> + + Walkthroughs + + + + Step-by-step tutorials for building with Keystone. + + + + Getting started + + + + If you’re new to Keystone begin here. These walkthroughs introduce the system, key concepts, + and show you how to get up and running with schema-driven development the Keystone way. + + + + + + + + Learn Keystone + + + + Learn how to build a functioning blog backend with relationships, auth, and session data + from an empty folder, and gain insights into Keystone’s core concepts along the way. + + + + {walkthroughs.map((item) => ( + + ))} + + + ) +} diff --git a/docs/app/(site)/docs/walkthroughs/page.tsx b/docs/app/(site)/docs/walkthroughs/page.tsx new file mode 100644 index 00000000000..081484041e1 --- /dev/null +++ b/docs/app/(site)/docs/walkthroughs/page.tsx @@ -0,0 +1,26 @@ +import { DocsLayout } from '../../../../components/docs/DocsLayout' +import { getFeaturedDocsMap } from '../../../../keystatic/get-featured-docs-map' +import { reader } from '../../../../keystatic/reader' +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 async function Docs () { + const docs = await getFeaturedDocsMap() + if (!docs) throw new Error('No `featuredDocs` found') + const featuredDocs = docs[0] + const [quickstart, ...walkthroughs] = featuredDocs.items + + 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..c27772a88a4 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 @@ -65,7 +61,7 @@ export default function ForDevelopers () { marginTop: '2.5rem', })} > - +