Skip to content

Commit

Permalink
migrate to app router, with emotion working
Browse files Browse the repository at this point in the history
  • Loading branch information
simonswiss committed Jul 19, 2024
1 parent 0decc55 commit 218f97a
Show file tree
Hide file tree
Showing 167 changed files with 1,559 additions and 1,496 deletions.
58 changes: 58 additions & 0 deletions docs/app/(site)/blog/[post]/page-client.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<BlogPage headings={headings} editPath={`docs/${params?.post}.md`}>
<Heading level={1} id="title" css={{ marginBottom: 0 }}>
{post.title}
</Heading>
<Type
as="p"
id="author"
look="body14"
css={{
marginTop: 'var(--space-large)',
marginBottom: '0.66em',
a: { textDecoration: 'none' },
}}
>
<em>
<span>Published on {formattedDateStr}</span>
{post.authorHandle ? (
<span>
{' '}
by{' '}
<Link href={post.authorHandle} target="_blank">
{post.authorName}
</Link>
</span>
) : (
<span> by {post.authorName}</span>
)}
</em>
</Type>
{post.content.children.map((child, i) => (
<Markdoc key={i} content={child} />
))}
</BlogPage>
)
}
71 changes: 71 additions & 0 deletions docs/app/(site)/blog/[post]/page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<PageClient
post={JSON.parse(
JSON.stringify({
...post,
// Prepare content for Markdoc renderer
content: transform(post.content.node, baseMarkdocConfig),
})
)}
/>
)
}

// Dynamic SEO page metadata
export async function generateMetadata ({ params }): Promise<Metadata> {
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,
}
}
99 changes: 26 additions & 73 deletions docs/pages/blog/index.tsx → docs/app/(site)/blog/page-client.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof getStaticProps>) {
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 (
<Page
title={'Keystone Blog'}
description={'Blog posts from the team maintaining Keystone.'}
ogImage={`${siteBaseUrl}/assets/blog/the-keystone-blog-cover.png`}
>
<Page>
<MWrapper css={{ marginTop: 0 }}>
<section
css={mq({
Expand Down Expand Up @@ -89,7 +59,7 @@ export default function Docs (props: InferGetStaticPropsType<typeof getStaticPro
marginBottom: 0,
}}
>
{posts.map(post => {
{posts.map((post) => {
return (
<li
css={mq({
Expand Down Expand Up @@ -129,20 +99,20 @@ export default function Docs (props: InferGetStaticPropsType<typeof getStaticPro
paddingRight: '0.5rem',
}}
>
<Link href={`/blog/${post.slug}`} passHref>
<a
css={{
textDecoration: 'none',
color: 'var(--text-heading)',
':hover': {
color: 'var(--link)',
},
}}
>
<Type as="h2" look="heading24" css={{ color: 'inherit' }}>
{post.frontmatter.title}
</Type>
</a>
<Link
href={`/blog/${post.slug}`}
passHref
css={{
textDecoration: 'none',
color: 'var(--text-heading)',
':hover': {
color: 'var(--link)',
},
}}
>
<Type as="h2" look="heading24" css={{ color: 'inherit' }}>
{post.frontmatter.title}
</Type>
</Link>
<Type as="p" look="body18" color="var(--muted)" css={{ paddingTop: '1rem' }}>
{post.frontmatter.description}
Expand All @@ -157,20 +127,3 @@ export default function Docs (props: InferGetStaticPropsType<typeof getStaticPro
</Page>
)
}

export async function getStaticProps (): Promise<
GetStaticPropsResult<{
posts: {
slug: string
frontmatter: Omit<Entry<typeof keystaticConfig['collections']['posts']>, '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 } }
}
47 changes: 47 additions & 0 deletions docs/app/(site)/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -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 <ClientPage posts={sortedPosts} />
}
Original file line number Diff line number Diff line change
@@ -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 (
<Page title="KeystoneJS Brand" description="Keystones brand assets and guidelines">
<Page>
<MWrapper>
<Pill grad="grad1">Branding</Pill>
<IntroWrapper>
Expand Down
10 changes: 10 additions & 0 deletions docs/app/(site)/branding/page.tsx
Original file line number Diff line number Diff line change
@@ -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 <PageClient />
}
33 changes: 33 additions & 0 deletions docs/app/(site)/docs/[...rest]/page-client.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<DocsPage
headings={headings}
editPath={`docs/${(params?.rest as string[]).join('/')}.md`}
>
<Heading level={1} id="title">
{document.title}
</Heading>

{document.content.children.map((child, i) => (
<Markdoc key={i} content={child} />
))}
</DocsPage>
)
}
Loading

0 comments on commit 218f97a

Please sign in to comment.