Skip to content

Commit

Permalink
migrate to app router (#141)
Browse files Browse the repository at this point in the history
* WIP [ci skip]

* WIP [ci skip]

* ga

* WIP [ci skip]

* WIP [ci skip]

* global layout

* fix notfound

* fix tag page

* use server

* prettier

* fix import path

* remove unused file

* show the profile in only the blog post page

* fix: Server Actions are not supported with static export.

* fix useRef error

* set NODE_ENV=production explicitly to fix builds
  • Loading branch information
fohte authored Nov 28, 2023
1 parent 0ae2082 commit e08dcb5
Show file tree
Hide file tree
Showing 34 changed files with 644 additions and 726 deletions.
25 changes: 25 additions & 0 deletions app/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from 'react'

import { Heading } from '@chakra-ui/react'
import { allPosts } from 'contentlayer/generated'

import { findPostFrontmatter } from '../../utils/contentlayer'
import { PostList } from '../../components/PostList'
import { Container } from '../../components/Container'

export default async function PostListPage() {
const posts = allPosts.map((post) => ({
slug: post._raw.flattenedPath,
frontmatter: findPostFrontmatter(post),
}))

return (
<Container backgroundColor="white">
<Heading size="md" my={4}>
記事一覧
</Heading>

<PostList posts={posts} />
</Container>
)
}
74 changes: 74 additions & 0 deletions app/blog/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as React from 'react'
import { Metadata, ResolvingMetadata } from 'next'
import { notFound } from 'next/navigation'
import { allPosts } from 'contentlayer/generated'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { ParsedUrlQuery } from 'node:querystring'
import { mdxComponents } from '../../../../components/mdx'
import { Heading, Text, Box, Divider } from '@chakra-ui/react'

import { PostFooterProfile } from '../../../../components/PostFooterProfile'
import { TagList } from '../../../../components/TagList'
import { Container } from '../../../../components/Container'
import { formatDate } from '../../../../utils/date'

type Props = {
params: Params
}

interface Params extends ParsedUrlQuery {
slug: string
}

export async function generateMetadata(
{ params: { slug } }: Props,
parent: ResolvingMetadata,
): Promise<Metadata> {
const post = allPosts.find((post) => post._raw.flattenedPath === slug)
if (!post) throw new Error(`Failed to find post with slug: ${slug}`)
const metadata: Metadata = {
title: post.title,
description: post.description,
openGraph: {
description: post.description,
type: 'article',
images: post.imagePath
? [{ url: post.imagePath }]
: (await parent).openGraph?.images,
},
}
return metadata
}

export async function generateStaticParams() {
return allPosts.map((post) => ({ slug: post._raw.flattenedPath }))
}

export default function PostPage({ params: { slug } }: Props) {
const post = allPosts.find((post) => post._raw.flattenedPath === slug)
if (!post) notFound()
const MDXContent = useMDXComponent(post.body.code)

return (
<Container backgroundColor="white" py={8}>
<Box mb={8}>
<Text fontSize="sm" mb={2}>
{formatDate(post.date)}
</Text>
<Heading as="h1" mb={{ base: 2, md: 3 }} size="lg">
{post.title}
</Heading>
{post.tags && (
<Box>
<TagList tags={post.tags}></TagList>
</Box>
)}
</Box>
<Box fontSize={{ base: 'sm', md: 'md' }} lineHeight="taller">
<MDXContent components={mdxComponents} />
</Box>
<Divider my={8} />
<PostFooterProfile />
</Container>
)
}
48 changes: 48 additions & 0 deletions app/blog/tags/[tag]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react'

import { flatMap } from 'remeda'
import { notFound } from 'next/navigation'
import { Heading } from '@chakra-ui/react'
import { ParsedUrlQuery } from 'node:querystring'

import { allPosts } from 'contentlayer/generated'
import { PostList } from '../../../../components/PostList'
import { Container } from '../../../../components/Container'
import { findPostFrontmatter } from '../../../../utils/contentlayer'

type Props = {
params: Params
}

interface Params extends ParsedUrlQuery {
tag: string
}

export default function TagPage({ params: { tag } }: Props) {
if (tag == null) {
notFound()
}

const posts = allPosts
.filter(({ tags }) => tags?.includes(tag))
.map((post) => ({
slug: post._raw.flattenedPath,
frontmatter: findPostFrontmatter(post),
}))

return (
<Container backgroundColor="white">
<Heading size="md" my={4}>
# {tag} の記事一覧
</Heading>

<PostList posts={posts} />
</Container>
)
}

export async function generateStaticParams() {
return flatMap(allPosts, (post) => post.tags)
.filter((tag) => tag != null)
.map((tag) => ({ tag }))
}
File renamed without changes
49 changes: 49 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Metadata, Viewport } from 'next'

import { Providers } from './providers'
import GlobalLayout from '../components/GlobalLayout'

export const metadata: Metadata = {
metadataBase: new URL('https://fohte.net'),
title: {
template: '%s | fohte.net',
default: 'fohte.net',
},
openGraph: {
siteName: 'fohte.net',
images: [
{
url: '/icon.png',
width: 500,
height: 500,
},
],
locale: 'ja_JP',
},
twitter: {
card: 'summary',
site: '@fohte',
creator: '@fohte',
},
}

export const viewport: Viewport = {
width: 'device-width',
initialScale: 1.0,
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
<Providers>
<GlobalLayout>{children}</GlobalLayout>
</Providers>
</body>
</html>
)
}
47 changes: 47 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as React from 'react'

import { Box, Heading, Text, Flex } from '@chakra-ui/react'

import { Container } from '../components/Container'
import { Link } from '../components/Link'
import { SocialList } from '../components/SocialList'

interface Props {}

const RootPage: React.FC<Props> = () => (
<Container>
<Flex justifyContent="center" flexDirection="column" gap={10}>
<Flex
justifyContent="center"
alignItems="center"
flexDirection="column"
gap={4}
>
<Heading>Fohte (Hayato Kawai)</Heading>
<Text>Gamer / Software Engineer (Cloud Infrastructure Engineer)</Text>
<Text>Love: Rhythm Games, Productivity, Neovim, Dvorak</Text>
</Flex>
<Flex flexDirection="column" gap={8}>
<Box as="section">
<Heading size="md" pb={2} mb={4} borderBottom="1px solid #ddd">
Socials
</Heading>
<SocialList />
</Box>
<Box as="section">
<Heading size="md" pb={2} mb={4} borderBottom="1px solid #ddd">
Career
</Heading>
<Text>
See:{' '}
<Link href="https://www.wantedly.com/id/fohte">
wantedly.com/id/fohte
</Link>
</Text>
</Box>
</Flex>
</Flex>
</Container>
)

export default RootPage
Loading

0 comments on commit e08dcb5

Please sign in to comment.