And so on ...
app//categories/[slug]/page.tsx
Copy import CategoryLayout from "@/app/layouts/CategoryLayout";
import { genPageMetadata } from "@/app/seo";
import { metadata } from "@/data/config/metadata";
import prisma from "@/lib/prisma";
export async function generateMetadata({
params,
}: {
params: { slug: string };
}) {
const categoryData = prisma.category.findUnique({
where: { slug: params.slug },
select: {
name: true,
slug: true,
},
});
const category = await categoryData;
if (!category) {
return genPageMetadata({
title: "Category not found",
});
}
return genPageMetadata({
title: `Best ${category.name} ${metadata.productLabel}s`,
description: `Find all the best ${category.name} ${metadata.productLabel}s.`,
url: `/categories/${category.slug}`,
});
}
export async function generateStaticParams() {
const categoriesData = prisma.category.findMany();
const categories = await categoriesData;
return categories.map((category) => ({ slug: category.slug }));
}
export default function Category({ params }: { params: { slug: string } }) {
return <CategoryLayout slug={params.slug} />;
}
genPageMetadata
can't be called on a client page ("use client") , keep your pages
file server side rendered and build a client layout.
Copy import { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: "*",
allow: "/",
disallow: [
"/dashboard*",
"/terms",
"/privacy",
"/stats",
"/opengraph-image?",
],
},
sitemap: `${process.env.NEXT_PUBLIC_APP_URL}/sitemap.xml`,
host: process.env.NEXT_PUBLIC_APP_URL,
};
}
Copy import { MetadataRoute } from "next";
import prisma from "@/lib/prisma";
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const siteUrl = process.env.NEXT_PUBLIC_APP_URL;
const categories = await prisma.category.findMany({
...
});
const categoryRoutes = categories.map((category) => {
const lastModified = category.products[0]?.createdAt || category.createdAt;
return {
url: `${siteUrl}/categories/${category.slug}`,
lastModified: lastModified.toISOString().split("T")[0],
};
});
...
const mainRoute = {
url: `${siteUrl}/`,
lastModified: latestproduct
? latestproduct.createdAt.toISOString().split("T")[0]
: new Date().toISOString().split("T")[0],
};
return [mainRoute, ...categoryRoutes, ...productRoutes];
}