diff --git a/app/api/articles/route.ts b/app/api/articles/route.ts
new file mode 100644
index 0000000..359a0bc
--- /dev/null
+++ b/app/api/articles/route.ts
@@ -0,0 +1,7 @@
+import {getAllArticles} from '@/lib/getAllArticles'
+
+export async function GET(request: Request) {
+ const articles = await getAllArticles(false)
+
+ return new Response(JSON.stringify(articles), {status: 200})
+}
diff --git a/components/layouts/ArticleLayout.tsx b/components/layouts/ArticleLayout.tsx
index e21e7e2..530268d 100644
--- a/components/layouts/ArticleLayout.tsx
+++ b/components/layouts/ArticleLayout.tsx
@@ -5,6 +5,7 @@ import {Prose} from '@/components/ui/Prose'
import {Views} from '@/components/ui/Views'
import {ArrowDownIcon} from '@/components/icons/ArrowDownIcon'
import {formatDate} from '@/lib/formatDate'
+import ArticleNav from '@/components/ui/ArticleNav'
type ArticleLayout = {
title: string
@@ -12,7 +13,6 @@ type ArticleLayout = {
description: string
slug: string
children?: ReactNode
- ogImage?: string
}
const gradients = [
@@ -26,10 +26,8 @@ const gradients = [
export function ArticleLayout({
title,
date,
- description,
slug,
children,
- ogImage
}: ArticleLayout) {
return (
@@ -60,6 +58,7 @@ export function ArticleLayout({
{children}
+
diff --git a/components/ui/ArticleNav.tsx b/components/ui/ArticleNav.tsx
new file mode 100644
index 0000000..92db6e0
--- /dev/null
+++ b/components/ui/ArticleNav.tsx
@@ -0,0 +1,89 @@
+'use client'
+
+import React, {ReactElement, useEffect, useState} from 'react'
+import fetcher from '@/lib/fetcher'
+import useSWR from 'swr'
+import {Card} from '@/components/ui/Card'
+import clsx from 'clsx'
+
+
+type Article = {
+ slug: string
+ authors: string
+ title: string
+ date: string
+ description: string
+}
+
+type FetchArticlesResponse = {
+ data: Article[]
+ error: string
+ isLoading: boolean
+}
+
+type ArticleNavProps = {
+ slug: string
+}
+
+type PaginationProps = {
+ next: Article | null
+ prev: Article | null
+}
+
+function useFetchArticles() {
+ const {data, error, isLoading} = useSWR(`/api/articles/`, fetcher) as FetchArticlesResponse
+
+ return {
+ articles: data,
+ isLoading,
+ isError: error
+ }
+}
+
+export default function ArticleNav({slug}: ArticleNavProps): ReactElement | null {
+ const {articles, isLoading, isError} = useFetchArticles()
+ const [{next, prev}, setPagination] = useState({next: null, prev: null})
+
+ useEffect(() => {
+ const findAdjacentArticles = (articles: Article[], slug: string) => {
+ if (articles) {
+ const index = articles.findIndex(article => article.slug === slug)
+ const next = index < articles.length - 1 ? articles[index + 1] : null
+ const prev = index > 0 ? articles[index - 1] : null
+
+ setPagination({next, prev})
+ }
+ }
+
+ findAdjacentArticles(articles, slug)
+ }, [articles, slug])
+
+ if (isError) return null
+
+ return (
+
+
+ {prev !== null &&
+
+
+ {prev.title}
+
+
+ }
+ {next !== null &&
+
+
+ {next.title}
+
+
+ }
+
+
+ )
+}
\ No newline at end of file
diff --git a/components/ui/Card.tsx b/components/ui/Card.tsx
index f3f08df..0167ab6 100644
--- a/components/ui/Card.tsx
+++ b/components/ui/Card.tsx
@@ -13,6 +13,7 @@ type Card = {
type CardLink = {
href: string
+ ariaLabel?: string
children: ReactNode
}
@@ -74,12 +75,12 @@ export function Card({
)
}
-Card.Link = function CardLink({href, children}: CardLink) {
+Card.Link = function CardLink({href, children, ariaLabel}: CardLink) {
return (
<>
-
+
{children}
@@ -89,7 +90,8 @@ Card.Link = function CardLink({href, children}: CardLink) {
Card.Title = function CardTitle({as: Component = 'h2', href, children}: CardTitle) {
return (
-
+
{href ? {children} : children}
)
diff --git a/lib/getAllArticles.ts b/lib/getAllArticles.ts
index fcbac42..3049f4d 100644
--- a/lib/getAllArticles.ts
+++ b/lib/getAllArticles.ts
@@ -12,12 +12,13 @@ async function importArticle(articleFilename: string) {
}
}
-export async function getAllArticles() {
+export async function getAllArticles(dateDesc = true) {
let articleFilenames = await glob(['*.mdx', '*/page.mdx'], {
cwd: path.join(process.cwd(), './app/writing'),
})
let articles = await Promise.all(articleFilenames.map(importArticle))
- return articles.sort((a, z) => a.date < z.date ? 1 : -1)
+ return dateDesc ? articles.sort((a, z) => a.date < z.date ? 1 : -1)
+ : articles.sort((a, z) => a.date > z.date ? 1 : -1)
}