Skip to content

Commit

Permalink
feat(app-router): switch to app router (#1252)
Browse files Browse the repository at this point in the history
* feat(app-router): switch to app router

- Refactor ant design, sandpack, and nprogress usage.
- Remove `next-seo`, use Next.js built-in Metadata API instead.
- Remove `<MetaHeader />` component.
- Rename metadata files.
- Add 'use client' directive to components that use client-side code.

* build(ts-paths): change resolve paths to `@/*`

* fix(app): migrate 404.tsx to not-found.tsx

* fix(app): refactor all pages components

* fix(app-tag): normalize tag name before using it as a filter

* fix(lib-posts): remove global postsData variable

* style: format code
  • Loading branch information
sabertazimi authored Apr 16, 2024
1 parent 5392e78 commit 849a184
Show file tree
Hide file tree
Showing 177 changed files with 765 additions and 921 deletions.
20 changes: 20 additions & 0 deletions app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Metadata } from 'next'
import { GithubCard } from '@/components'
import { Layout } from '@/layouts'
import { getBuildTime, getGitHubData, getPostsMeta } from '@/lib'

export const metadata: Metadata = {
title: 'About Me',
}

export default async function About() {
const buildTime = getBuildTime()
const { profile, repos } = await getGitHubData()
const postsMeta = await getPostsMeta()

return (
<Layout banner="About Me" buildTime={buildTime} posts={postsMeta}>
<GithubCard profile={profile} repos={repos} />
</Layout>
)
}
19 changes: 19 additions & 0 deletions app/books/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Metadata } from 'next'
import { BooksGrid } from '@/components'
import { Layout } from '@/layouts'
import { getBuildTime, getPostsMeta } from '@/lib'

export const metadata: Metadata = {
title: 'Books',
}

export default async function Books() {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()

return (
<Layout banner="Books" buildTime={buildTime} posts={postsMeta}>
<BooksGrid />
</Layout>
)
}
File renamed without changes.
42 changes: 42 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { AntdRegistry } from '@ant-design/nextjs-registry'
import type { Metadata, Viewport } from 'next'
import type { ReactNode } from 'react'
import ProgressBarProvider from '@/components/ProgressBarProvider'
import SandpackProvider from '@/components/SandpackProvider'
import { getMetadata, getViewport } from '@/config'

// Keep stylesheets importing order
import '@/styles/globals.css'
import '@/components/Article/Article.css'
import '@/components/Button/Button.css'
import '@/components/Card/Card.css'
import '@/components/Skeleton/Skeleton.css'

export function generateMetadata(): Metadata {
return getMetadata()
}

export function generateViewport(): Viewport {
return getViewport()
}

export default function RootLayout({
children,
}: {
children: ReactNode
}) {
return (
<html lang="en">
<head>
<SandpackProvider />
</head>
<body>
<AntdRegistry>
<ProgressBarProvider>
{children}
</ProgressBarProvider>
</AntdRegistry>
</body>
</html>
)
}
File renamed without changes.
21 changes: 21 additions & 0 deletions app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Metadata } from 'next'
import { NotFoundResult } from '@/components'
import { Layout } from '@/layouts'
import { getBuildTime, getPostsMeta } from '@/lib'

export const metadata: Metadata = {
title: 'Exploring',
}

export default async function NotFound() {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()

return (
<div>
<Layout banner="Exploring" buildTime={buildTime} posts={postsMeta}>
<NotFoundResult />
</Layout>
</div>
)
}
11 changes: 11 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { LandingNav, TypingTitle } from '@/components'
import { LandingLayout } from '@/layouts'

export default function Home() {
return (
<LandingLayout>
<LandingNav />
<TypingTitle />
</LandingLayout>
)
}
40 changes: 40 additions & 0 deletions app/post/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { ParsedUrlQuery } from 'node:querystring'
import type { Metadata } from 'next'
import { Article } from '@/components'
import { getMetadata } from '@/config'
import { PostLayout } from '@/layouts'
import { getBuildTime, getPostData, getPostsMeta } from '@/lib'
import 'katex/dist/katex.css'

interface QueryParams extends ParsedUrlQuery {
slug: string
}

export async function generateStaticParams() {
const postsMeta = await getPostsMeta()
return postsMeta.map(({ slug }) => ({
slug,
}))
}

export async function generateMetadata({ params }: { params: QueryParams }): Promise<Metadata> {
const postData = await getPostData(params.slug)
return postData ? getMetadata({ title: postData.title }) : getMetadata()
}

export default async function Post({ params }: { params: QueryParams }) {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()
const postData = await getPostData(params.slug)

return (
postData && (
<PostLayout
buildTime={buildTime}
posts={postsMeta}
>
<Article post={postData} />
</PostLayout>
)
)
}
19 changes: 19 additions & 0 deletions app/posts/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Metadata } from 'next'
import { PostsGrid } from '@/components'
import { Layout } from '@/layouts'
import { getBuildTime, getPostsMeta } from '@/lib'

export const metadata: Metadata = {
title: 'Posts',
}

export default async function Posts() {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()

return (
<Layout banner="Posts" buildTime={buildTime} posts={postsMeta}>
<PostsGrid posts={postsMeta} />
</Layout>
)
}
39 changes: 39 additions & 0 deletions app/tag/[tag]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { ParsedUrlQuery } from 'node:querystring'
import type { Metadata } from 'next'
import { PostsList, TagsCloud } from '@/components'
import { getMetadata } from '@/config'
import { Layout } from '@/layouts'
import { getBuildTime, getPostsMeta, getTagsData } from '@/lib'

interface QueryParams extends ParsedUrlQuery {
tag: string
}

export async function generateStaticParams() {
const tagsData = await getTagsData()
return Object.keys(tagsData).map(tag => ({
tag,
}))
}

export async function generateMetadata({ params }: { params: QueryParams }): Promise<Metadata> {
return getMetadata({ title: params.tag })
}

export default async function Tags({ params }: { params: QueryParams }) {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()
const tagsData = await getTagsData()
const activeTag = decodeURI(params.tag)

const postsMetaByTag = postsMeta.filter(
({ tags }) => tags && tags.includes(activeTag),
)

return (
<Layout banner={activeTag} buildTime={buildTime} posts={postsMeta}>
<TagsCloud tags={tagsData} activeTag={activeTag} />
<PostsList posts={postsMetaByTag} />
</Layout>
)
}
21 changes: 21 additions & 0 deletions app/tags/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Metadata } from 'next'
import { PostsList, TagsCloud } from '@/components'
import { Layout } from '@/layouts'
import { getBuildTime, getPostsMeta, getTagsData } from '@/lib'

export const metadata: Metadata = {
title: 'Tags',
}

export default async function Tags() {
const buildTime = getBuildTime()
const postsMeta = await getPostsMeta()
const tagsData = await getTagsData()

return (
<Layout banner="Tags" buildTime={buildTime} posts={postsMeta}>
<TagsCloud tags={tagsData} />
<PostsList posts={postsMeta} />
</Layout>
)
}
4 changes: 2 additions & 2 deletions components/Article/Article.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import mockData from '@mocks/data'
import { render } from '@utils'
import Article from './Article'
import mockData from '@/mocks/data'
import { render } from '@/utils'

describe('Article', () => {
const mockBasePost = mockData.basePosts[0]
Expand Down
12 changes: 6 additions & 6 deletions components/Article/Article.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import Container from '@components/Container'
import Divider from '@components/Divider'
import { Comment } from '@components/Icons'
import SocialGroup from '@components/SocialGroup'
import { siteConfig } from '@config'
import type { PostType, SiteConfig } from '@types'
import ArticleComments from './ArticleComments'
import ArticleContent from './ArticleContent'
import ArticleHeader from './ArticleHeader'
import ArticleNav from './ArticleNav'
import ArticleToc from './ArticleToc'
import Container from '@/components/Container'
import Divider from '@/components/Divider'
import { Comment } from '@/components/Icons'
import SocialGroup from '@/components/SocialGroup'
import { siteConfig } from '@/config'
import type { PostType, SiteConfig } from '@/types'

interface Props {
post: PostType
Expand Down
2 changes: 1 addition & 1 deletion components/Article/ArticleComments.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render } from '@utils'
import { axe } from 'jest-axe'
import ArticleComments from './ArticleComments'
import { render } from '@/utils'

describe('ArticleComments', () => {
it('should render correctly (snapshot)', () => {
Expand Down
8 changes: 5 additions & 3 deletions components/Article/ArticleComments.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { cx } from '@components/utils'
import { siteConfig } from '@config'
import { useDisqus } from '@hooks'
'use client'

import cx from 'classnames'
import styles from './ArticleComments.module.css'
import { siteConfig } from '@/config'
import { useDisqus } from '@/hooks'

interface Props {
url?: string
Expand Down
6 changes: 4 additions & 2 deletions components/Article/ArticleContent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client'

import { MDXRemote } from '@alisowski/next-mdx-remote'
import MDX from '@components/MDX'
import type { PostType } from '@types'
import MDX from '@/components/MDX'
import type { PostType } from '@/types'

interface Props {
source: PostType['source']
Expand Down
12 changes: 6 additions & 6 deletions components/Article/ArticleHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { H1 } from '@components/Headings'
import { Calendar, ClockCircle, Edit } from '@components/Icons'
import { Slide } from '@components/Motion'
import { IconTag, LinkTag } from '@components/Tags'
import { siteConfig } from '@config'
import type { PostMeta } from '@types'
import styles from './ArticleHeader.module.css'
import { H1 } from '@/components/Headings'
import { Calendar, ClockCircle, Edit } from '@/components/Icons'
import { Slide } from '@/components/Motion'
import { IconTag, LinkTag } from '@/components/Tags'
import { siteConfig } from '@/config'
import type { PostMeta } from '@/types'

interface Props {
post: PostMeta
Expand Down
10 changes: 5 additions & 5 deletions components/Article/ArticleNav.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import FlexContainer from '@components/FlexContainer'
import { ArrowLeft, ArrowRight, Home } from '@components/Icons'
import Link from '@components/Link'
import { Bounce } from '@components/Motion'
import type { PostMeta } from '@types'
import FlexContainer from '@/components/FlexContainer'
import { ArrowLeft, ArrowRight, Home } from '@/components/Icons'
import Link from '@/components/Link'
import { Bounce } from '@/components/Motion'
import type { PostMeta } from '@/types'

interface Props {
prevPost: PostMeta['prevPost']
Expand Down
2 changes: 1 addition & 1 deletion components/Article/ArticleToc.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from '@utils'
import ArticleToc from './ArticleToc'
import { render } from '@/utils'

describe('ArticleToc', () => {
it('should render correctly (snapshot)', () => {
Expand Down
4 changes: 3 additions & 1 deletion components/Article/ArticleToc.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Anchor from '@components/Anchor'
'use client'

import { useEffect, useState } from 'react'
import styles from './ArticleToc.module.css'
import Anchor from '@/components/Anchor'

interface Props {
slug: string
Expand Down
2 changes: 1 addition & 1 deletion components/Aside/Aside.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from '@utils'
import Aside from './Aside'
import { render } from '@/utils'

describe('Aside', () => {
const types = [
Expand Down
4 changes: 2 additions & 2 deletions components/Aside/Aside.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Alert from '@components/Alert'
import { cx } from '@components/utils'
import cx from 'classnames'
import type { ReactNode } from 'react'
import styles from './Aside.module.css'
import Alert from '@/components/Alert'

interface Props {
type?: string
Expand Down
2 changes: 2 additions & 0 deletions components/BackTop/BackTop.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client'

import type { BackTopProps } from 'antd'
import { FloatButton } from 'antd'

Expand Down
2 changes: 1 addition & 1 deletion components/Blockquote/Blockquote.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render } from '@utils'
import Blockquote from './Blockquote'
import { render } from '@/utils'

describe('Blockquote', () => {
it('should render correctly (snapshot)', () => {
Expand Down
2 changes: 1 addition & 1 deletion components/Blockquote/Blockquote.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cx } from '@components/utils'
import cx from 'classnames'
import type { BlockquoteHTMLAttributes } from 'react'
import styles from './Blockquote.module.css'

Expand Down
Loading

0 comments on commit 849a184

Please sign in to comment.