feat: make blog index page statically generated

This commit is contained in:
Dorian Niemiec 2024-09-07 14:24:30 +02:00
parent 1e935d3aef
commit 8c73ec7d8e
3 changed files with 91 additions and 15 deletions

View file

@ -35,13 +35,7 @@ export const metadata: Metadata = {
} }
}; };
const BlogPage = async ({ const BlogPage = async () => {
searchParams
}: {
searchParams: { page?: string };
}) => {
// Optionally, you can fetch some initial data here if needed.
return ( return (
<section <section
id="blog" id="blog"
@ -58,7 +52,7 @@ const BlogPage = async ({
</Button> </Button>
</Link> </Link>
</p> </p>
<BlogCards searchParams={searchParams} /> <BlogCards page={1} />
</section> </section>
); );
}; };

View file

@ -0,0 +1,80 @@
import React from "react";
import { client } from "@/lib/sanity";
import { Metadata } from "next";
import BlogCards from "@/components/cards/BlogCards";
import { Rss } from "lucide-react";
import { Button } from "@/components/ui/button";
import Link from "next/link";
export const metadata: Metadata = {
title: "Blog - SVR.JS",
description:
"Welcome to the SVR.JS Blog! Explore our latest blog posts featuring web development, web application security, and web server administration tips. Stay tuned for the latest SVR.JS updates.",
openGraph: {
title: "Blog - SVR.JS",
description:
"Welcome to the SVR.JS Blog! Explore our latest blog posts featuring web development, web application security, and web server administration tips. Stay tuned for the latest SVR.JS updates.",
url: "https://svrjs.org/blog",
type: "website",
images: [
{
url: "https://svrjs.vercel.app/metadata/svrjs-cover.png",
width: 800,
height: 600,
alt: "Blog - SVR.JS"
}
]
},
twitter: {
card: "summary_large_image",
site: "@SVR_JS",
title: "Blog - SVR.JS",
description:
"Welcome to the SVR.JS Blog! Explore our latest blog posts featuring web development, web application security, and web server administration tips. Stay tuned for the latest SVR.JS updates.",
images: ["https://svrjs.vercel.app/metadata/svrjs-cover.png"],
creator: "@SVR_JS"
}
};
const BlogPage = async ({ params }: { params: { id: string } }) => {
// Optionally, you can fetch some initial data here if needed.
return (
<section
id="blog"
className="wrapper container py-24 md:py-28 gap-2 flex-center flex-col"
>
<h1 className="text-3xl md:text-5xl mb-3 pb-1 md:pb-2 font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
SVR.JS Blog Post
</h1>
<p className="text-muted-foreground flex-center mb-2">
Stay updated with our latest blog posts by subscribing to our
<Link href="/rss.xml" rel="alternate" type="application/rss+xml">
<Button variant={"link"} className="mx-0 px-2">
<Rss className="w-5 h-5 mr-1" /> RSS feed
</Button>
</Link>
</p>
<BlogCards page={parseInt(params.id)} />
</section>
);
};
export async function generateStaticParams() {
// Change in BlogCards component too!
const cardsPerPage = 6;
const totalPostsQuery = `count(*[_type == 'blog'])`;
const totalPosts: number = await client.fetch(totalPostsQuery);
const totalPages = Math.ceil(totalPosts / cardsPerPage);
let ids: any[] = [];
for (let i = 1; i <= totalPages; i++) {
ids.push({ id: i.toString() });
}
return ids;
}
export default BlogPage;

View file

@ -22,14 +22,16 @@ interface BlogPostcard {
_createdAt: string; _createdAt: string;
} }
interface BlogCardsProps { interface BlogCardInterface {
searchParams: { page?: string }; page: number;
} }
const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => { const BlogCards: React.FC<BlogCardInterface> = async (props) => {
"use server"; "use server";
// Change in /blog/page/[id] route too!
const cardsPerPage = 6; const cardsPerPage = 6;
const currentPage = searchParams.page ? parseInt(searchParams.page) : 1; const currentPage = props.page;
const query = `*[_type == 'blog'] | order(_createdAt desc) { const query = `*[_type == 'blog'] | order(_createdAt desc) {
title, title,
@ -107,13 +109,13 @@ const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => {
<PaginationContent> <PaginationContent>
<PaginationItem> <PaginationItem>
{currentPage > 1 && ( {currentPage > 1 && (
<PaginationPrevious href={`?page=${currentPage - 1}`} /> <PaginationPrevious href={`/blog/page/${currentPage - 1}`} />
)} )}
</PaginationItem> </PaginationItem>
{Array.from({ length: totalPages }).map((_, i) => ( {Array.from({ length: totalPages }).map((_, i) => (
<PaginationItem key={i}> <PaginationItem key={i}>
<PaginationLink <PaginationLink
href={`?page=${i + 1}`} href={`/blog/page/${i + 1}`}
isActive={currentPage === i + 1} isActive={currentPage === i + 1}
> >
{i + 1} {i + 1}
@ -122,7 +124,7 @@ const BlogCards: React.FC<BlogCardsProps> = async ({ searchParams }) => {
))} ))}
<PaginationItem> <PaginationItem>
{currentPage < totalPages && ( {currentPage < totalPages && (
<PaginationNext href={`?page=${currentPage + 1}`} /> <PaginationNext href={`/blog/page/${currentPage + 1}`} />
)} )}
</PaginationItem> </PaginationItem>
</PaginationContent> </PaginationContent>