open-prompt / src /app /explore /page.tsx
anky2002's picture
perf: add ISR revalidation (30s) to explore page
e13aca4 verified
import { Suspense } from "react"
import { Metadata } from "next"
import prisma from "@/lib/prisma"
import { ExploreClient } from "@/components/explore/explore-client"
import { Loader2 } from "lucide-react"
import { generateSEO } from "@/lib/seo"
const BASE_URL = process.env.NEXT_PUBLIC_APP_URL || 'https://open-prompt.netlify.app'
// Revalidate every 30 seconds instead of force-dynamic
export const revalidate = 30
export const metadata: Metadata = generateSEO({
title: "Explore AI Prompts | OpenPrompt",
description: "Discover and run AI prompts created by the community. Find prompts for content, coding, marketing, business, education, and more.",
url: `${BASE_URL}/explore`,
keywords: ["explore prompts", "discover AI prompts", "community prompts", "prompt search", "AI prompt library"],
}) as Metadata
async function getInitialPrompts(category?: string, search?: string, sort?: string) {
try {
const orderBy: Record<string, 'asc' | 'desc'>[] = []
switch (sort) {
case 'recent':
orderBy.push({ createdAt: 'desc' })
break
case 'stars':
orderBy.push({ starsCount: 'desc' })
break
case 'runs':
orderBy.push({ totalRuns: 'desc' })
break
default:
orderBy.push({ totalRuns: 'desc' })
}
orderBy.push({ id: 'desc' })
const where: Record<string, unknown> = {
visibility: 'public',
}
if (category) {
where.category = category
}
if (search) {
where.OR = [
{ title: { contains: search, mode: 'insensitive' } },
{ description: { contains: search, mode: 'insensitive' } },
]
}
const prompts = await prisma.prompt.findMany({
where,
include: {
creator: {
select: {
name: true,
username: true,
image: true,
},
},
},
orderBy,
take: 12,
})
return prompts
} catch (error) {
console.error('Explore page data fetch error:', error)
return []
}
}
interface ExplorePageProps {
searchParams: Promise<{ [key: string]: string | undefined }>
}
export default async function ExplorePage({ searchParams }: ExplorePageProps) {
const params = await searchParams
const initialPrompts = await getInitialPrompts(
params.category,
params.q,
params.sort
)
return (
<div className="container mx-auto px-4 py-8 max-w-7xl">
{/* Page Header */}
<div className="mb-8">
<h1 className="text-3xl md:text-4xl font-serif font-medium mb-3">
Explore <span className="text-gradient italic">Prompts</span>
</h1>
<p className="text-muted-foreground text-lg">
Discover AI prompts created by the community
</p>
</div>
{/* Client Component with Search/Filter */}
<Suspense fallback={
<div className="flex items-center justify-center py-16">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
}>
<ExploreClient initialPrompts={initialPrompts} />
</Suspense>
</div>
)
}