import { Breadcrumb } from '@thedaviddias/design-system/breadcrumb' import type { Metadata } from 'next' import { notFound } from 'next/navigation' import { getHomePageData } from '@/actions/get-home-page-data' import { CategoryWebsitesList } from '@/components/category-websites-list' import { JsonLd } from '@/components/json-ld' import { AppSidebar } from '@/components/layout/app-sidebar' import { FeaturedGuidesSection } from '@/components/sections/featured-guides-section' import { NewsletterSection } from '@/components/sections/newsletter-section' import { ToolsSection } from '@/components/sections/tools-section' import { categories, getCategoryBySlug } from '@/lib/categories' import { getGuides } from '@/lib/content-loader' import { getCategorySEO } from '@/lib/seo/category-seo' import { generateDynamicMetadata, optimizeMetaDescription } from '@/lib/seo/seo-config' interface CategoryPageProps { params: Promise<{ category: string }> } /** * Generates static params for all category pages */ export async function generateStaticParams() { // Generate static params for all categories return categories.map(category => ({ category: category.slug })) } /** * Generates metadata for category pages with SEO-optimized descriptions */ export async function generateMetadata({ params }: CategoryPageProps): Promise { const resolvedParams = await params const category = getCategoryBySlug(resolvedParams.category) if (!category) { return { title: 'Category Not Found', description: 'The requested category could not be found.' } } // Get dynamic count and SEO content const { allProjects } = await getHomePageData() const categoryProjectsCount = category.slug === 'featured' ? allProjects.filter(p => p.featured === true).length : allProjects.filter(p => p.category === category.slug).length const seoContent = getCategorySEO(category.slug, category) // Enhanced title with count for better CTR const title = categoryProjectsCount > 0 ? `${categoryProjectsCount}+ ${seoContent.metaTitle}` : seoContent.metaTitle // Use SEO-optimized description const description = categoryProjectsCount > 0 ? `${categoryProjectsCount}+ websites. ${seoContent.metaDescription}` : seoContent.metaDescription return generateDynamicMetadata({ type: 'category', name: title, description: optimizeMetaDescription(description), slug: category.slug, additionalKeywords: seoContent.keywords }) } export default async function CategoryPage({ params }: CategoryPageProps) { const resolvedParams = await params const category = getCategoryBySlug(resolvedParams.category) if (!category) { notFound() } const { allProjects, featuredProjects } = await getHomePageData() const featuredGuides = await getGuides() const seoContent = getCategorySEO(category.slug, category) // Special handling for featured category let categoryProjects = [] if (category.slug === 'featured') { // For featured category, show all projects with featured: true categoryProjects = allProjects .filter(project => project.featured === true) .sort((a, b) => a.name.localeCompare(b.name)) } else { // Filter projects by category and sort alphabetically by default categoryProjects = allProjects .filter(project => project.category === category.slug) .sort((a, b) => a.name.localeCompare(b.name)) } return ( <> ({ '@type': 'ListItem', position: index + 1, url: project.website, name: project.name, description: project.description })), mainEntity: { '@type': 'ItemList', name: `${category.name} Websites and Tools`, description: category.description, numberOfItems: categoryProjects.length, itemListOrder: 'https://schema.org/ItemListOrderAscending', itemListElement: categoryProjects.slice(0, 20).map((project, index) => ({ '@type': 'Thing', position: index + 1, url: project.website, name: project.name })) }, publisher: { '@type': 'Organization', name: 'llms.txt hub', url: 'https://llmstxthub.com', logo: { '@type': 'ImageObject', url: 'https://llmstxthub.com/logo.png' } }, datePublished: new Date().toISOString(), dateModified: new Date().toISOString() }} /> {/* FAQ Structured Data if available */} {seoContent.faqQuestions && seoContent.faqQuestions.length > 0 && ( ({ '@type': 'Question', name: faq.question, acceptedAnswer: { '@type': 'Answer', text: faq.answer } })) }} /> )}
{/* Breadcrumb Navigation */} {/* Category Websites Section */}

{seoContent.h1Title}

{seoContent.introText}

) }