diff --git a/app/categories/[categorySlug]/page.tsx b/app/(withRecent)/categories/[categorySlug]/page.tsx similarity index 81% rename from app/categories/[categorySlug]/page.tsx rename to app/(withRecent)/categories/[categorySlug]/page.tsx index 58e8eec..fbf602c 100644 --- a/app/categories/[categorySlug]/page.tsx +++ b/app/(withRecent)/categories/[categorySlug]/page.tsx @@ -16,6 +16,13 @@ export async function generateMetadata({ params }: CategoryPageProps): Promise { + return { + title: `Categories | ${metadata.title!.toString()}`, + description: 'List of categories', + openGraph: { + type: 'website', + title: `Categories | ${metadata.title!.toString()}`, + description: 'List of categories', + url: process.env.SITE_URL + '/categories', + siteName: metadata.title!.toString(), + }, + } +} + +export default function CategoriesPage() { + const categories = getAllCategories() + const posts = getAllPostsMeta() + const categoryNames = Object.keys(categories) + + return ( +
+
~/categories
+ + +
+ ) +} diff --git a/app/(withRecent)/layout.tsx b/app/(withRecent)/layout.tsx new file mode 100644 index 0000000..0a1041f --- /dev/null +++ b/app/(withRecent)/layout.tsx @@ -0,0 +1,10 @@ +import { RecentlyUpdatedPosts } from '@/components/common/RecentlyUpdatedPosts' + +export default function WithRecentLayout({ children }: { children: React.ReactNode }) { + return ( + <> + {children} + + + ) +} diff --git a/app/(withRecent)/page.tsx b/app/(withRecent)/page.tsx new file mode 100644 index 0000000..8fa0f5a --- /dev/null +++ b/app/(withRecent)/page.tsx @@ -0,0 +1,41 @@ +import { getAllPostsMeta } from '@/lib/posts' +import { Post } from '@/components/common/Post' + +export default function BlogIndex() { + const posts = getAllPostsMeta() + + const rest = posts.slice(1) + const rows = [] + for (let i = 0; i < rest.length; i += 2) { + rows.push(rest.slice(i, i + 2)) + } + + return ( +
+
+ {posts.length === 0 ? ( +
+ No published posts yet. +
+ ) : ( + <> + + +
+ {rows.map((row) => { + const rowHasImage = row.some((p) => p.coverImage) + return ( +
+ {row.map((post) => ( + + ))} +
+ ) + })} +
+ + )} +
+
+ ) +} diff --git a/app/categories/page.tsx b/app/categories/page.tsx deleted file mode 100644 index 73ddf6f..0000000 --- a/app/categories/page.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { getAllCategories } from '@/lib/categories' -import { getAllPostsMeta } from '@/lib/posts' -import { slugify } from '@/utils/slug' -import type { Metadata } from 'next' -import Link from 'next/link' -import { metadata } from '@/app/metadata' - -export async function generateMetadata(): Promise { - return { title: `Categories | ${metadata.title!.toString()}`, description: 'List of categories' } -} - -export default function CategoriesPage() { - const categories = getAllCategories() - const posts = getAllPostsMeta() - - return ( -
-
-

Categories

-
    - {Object.keys(categories).map((category) => ( -
  • - - {category} ({categories[category]}) - - -
      - {posts - .filter((post) => post.category === category) - .map((post) => ( -
    • - {post.title} -
    • - ))} -
    -
  • - ))} -
-
-
-
- ) -} diff --git a/app/globals.css b/app/globals.css index fd6949c..0eb6f0a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -43,7 +43,8 @@ body { @apply list-decimal; } - ul, ol { + ul, + ol { @apply list-outside; } @@ -151,7 +152,7 @@ dd { } .prose a { - @apply text-accent; + @apply text-accent hover:underline focus:underline cursor-pointer; } .prose ul:not(.task-list-container) { diff --git a/app/metadata.ts b/app/metadata.ts new file mode 100644 index 0000000..de2bbea --- /dev/null +++ b/app/metadata.ts @@ -0,0 +1,14 @@ +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Ephemeris", + description: "A blog about me and my interests", + creator: "hangerthem", + openGraph: { + type: "website", + title: "Ephemeris", + description: "A blog about me and my interests", + url: process.env.SITE_URL, + siteName: "Ephemeris", + }, +} \ No newline at end of file diff --git a/app/metadata.tsx b/app/metadata.tsx deleted file mode 100644 index cbb1393..0000000 --- a/app/metadata.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { Metadata } from "next"; - -export const metadata: Metadata = { - title: "Ephemeris", - description: "A blog about me and my interests", - creator: "hangerthem", -} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx deleted file mode 100644 index a70dec9..0000000 --- a/app/page.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { getAllPostsMeta } from '@/lib/posts' -import { Post } from '@/components/common/Post' -import Link from 'next/link' - -export default function BlogIndex() { - const posts = getAllPostsMeta() - - const rest = posts.slice(1) - const rows = [] - for (let i = 0; i < rest.length; i += 2) { - rows.push(rest.slice(i, i + 2)) - } - - return ( - <> -
-
- {posts.length === 0 ? ( -
- No published posts yet. -
- ) : ( - <> - - -
- {rows.map((row) => { - const rowHasImage = row.some((p) => p.coverImage) - return ( -
- {row.map((post) => ( - - ))} -
- ) - })} -
- - )} -
-
- - - ) -} diff --git a/app/posts/[slug]/page.tsx b/app/posts/[slug]/page.tsx index b9870fe..151e2ac 100644 --- a/app/posts/[slug]/page.tsx +++ b/app/posts/[slug]/page.tsx @@ -2,7 +2,8 @@ import { metadata } from '@/app/metadata' import { ImageWrapper } from '@/components/common/ImageWrapper' import { ShareLinks } from '@/components/common/ShareLinks' import { TableOfContents } from '@/components/common/TableOfContents' -import { getAllPostSlugs, getPostBySlug } from '@/lib/posts' +import { getAllPostSlugs, getNextAndPreviousPosts, getPostBySlug } from '@/lib/posts' +import { slugify } from '@/utils/slug' import type { Metadata } from 'next' import Link from 'next/link' @@ -19,19 +20,33 @@ export async function generateMetadata({ }): Promise { const { slug } = await params const { meta } = await getPostBySlug(slug) - return { title: `${meta.title} | ${metadata.title!.toString()}`, description: meta.description } + return { + title: `${meta.title} | ${metadata.title!.toString()}`, + description: meta.description, + openGraph: { + type: 'article', + title: `${meta.title} | ${metadata.title!.toString()}`, + description: meta.description, + url: process.env.SITE_URL + `/posts/${slug}`, + images: meta.coverImage ? [meta.coverImage] : undefined, + tags: meta.tags, + ...(meta.updated && { modifiedTime: new Date(meta.updated).toISOString() }), + siteName: metadata.title!.toString(), + }, + } } export default async function Post({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params const { meta, content, tableOfContents } = await getPostBySlug(slug) + const { next, previous } = getNextAndPreviousPosts(slug) return (
{meta.category && ( {meta.category} @@ -99,6 +114,29 @@ export default async function Post({ params }: { params: Promise<{ slug: string description={meta.description} />
+ +
+ {previous ? ( + + ← {previous.title} + + ) : ( +
+ )} + {next ? ( + + {next.title} → + + ) : ( +
+ )} +