diff --git a/web/src/app/api/agents/route.ts b/web/src/app/api/agents/route.ts index 23431c1e20..ec86a22feb 100644 --- a/web/src/app/api/agents/route.ts +++ b/web/src/app/api/agents/route.ts @@ -6,8 +6,8 @@ import { unstable_cache } from 'next/cache' import { logger } from '@/util/logger' -// Cache for 60 seconds with stale-while-revalidate -export const revalidate = 60 +// Enable static generation for API route +export const revalidate = 600 // Cache for 10 minutes // Cached function for expensive agent aggregations const getCachedAgents = unstable_cache( @@ -251,7 +251,7 @@ const getCachedAgents = unstable_cache( }, ['agents-data'], { - revalidate: 60, + revalidate: 60 * 10, // Cache for 10 minutes tags: ['agents'], } ) @@ -265,9 +265,13 @@ export async function GET() { // Add cache headers for CDN and browser caching response.headers.set( 'Cache-Control', - 'public, max-age=60, s-maxage=60, stale-while-revalidate=300' + 'public, max-age=600, s-maxage=600, stale-while-revalidate=600' ) + // Add additional headers for better CDN caching + response.headers.set('Vary', 'Accept-Encoding') + response.headers.set('X-Content-Type-Options', 'nosniff') + return response } catch (error) { logger.error({ error }, 'Error fetching agents') diff --git a/web/src/app/store/page.tsx b/web/src/app/store/page.tsx index 0b34f043ab..9a33a86c39 100644 --- a/web/src/app/store/page.tsx +++ b/web/src/app/store/page.tsx @@ -1,7 +1,5 @@ import { Suspense } from 'react' import { Metadata } from 'next' -import { getServerSession } from 'next-auth/next' -import { authOptions } from '@/app/api/auth/[...nextauth]/auth-options' import { unstable_cache } from 'next/cache' import AgentStoreClient from './store-client' @@ -84,21 +82,19 @@ export const metadata: Metadata = { }, } -// Enable static generation with revalidation -export const revalidate = 60 +// Enable static site generation with ISR +export const revalidate = 60 * 10 // Revalidate every hour interface StorePageProps { searchParams: { [key: string]: string | string[] | undefined } } export default async function StorePage({ searchParams }: StorePageProps) { - // Get session for conditional rendering - const session = await getServerSession(authOptions) - - // Fetch agents data at build time / on revalidation + // Fetch agents data at build time const agentsData = await getCachedAgentsData() - // For now, pass empty array for publishers - client will handle this + // For static generation, we don't pass session data + // The client will handle authentication state const userPublishers: PublisherProfileResponse[] = [] return ( @@ -106,7 +102,7 @@ export default async function StorePage({ searchParams }: StorePageProps) { diff --git a/web/src/app/store/store-client.tsx b/web/src/app/store/store-client.tsx index d5e72aa034..978303d9a2 100644 --- a/web/src/app/store/store-client.tsx +++ b/web/src/app/store/store-client.tsx @@ -3,6 +3,7 @@ import { useState, useMemo, useCallback, memo, useEffect, useRef } from 'react' import { useQuery } from '@tanstack/react-query' import { useWindowVirtualizer } from '@tanstack/react-virtual' +import { useSession } from 'next-auth/react' import { Search, TrendingUp, @@ -29,7 +30,7 @@ import { SelectValue, } from '@/components/ui/select' import { toast } from '@/components/ui/use-toast' -import { formatRelativeTime } from '@/lib/date-utils' +import { RelativeTime } from '@/components/ui/relative-time' import { cn } from '@/lib/utils' import { useResponsiveColumns } from '@/hooks/use-responsive-columns' import type { Session } from 'next-auth' @@ -93,9 +94,12 @@ const EDITORS_CHOICE_AGENTS = [ export default function AgentStoreClient({ initialAgents, initialPublishers, - session, + session: initialSession, searchParams, }: AgentStoreClientProps) { + // Use client-side session for authentication state + const { data: clientSession } = useSession() + const session = clientSession || initialSession const [searchQuery, setSearchQuery] = useState( (searchParams.search as string) || '' ) @@ -403,7 +407,7 @@ export default function AgentStoreClient({ className="text-xs text-muted-foreground/60" title={new Date(agent.last_used).toLocaleString()} > - Used {formatRelativeTime(agent.last_used)} + Used )} diff --git a/web/src/components/ui/relative-time.tsx b/web/src/components/ui/relative-time.tsx new file mode 100644 index 0000000000..8712596b74 --- /dev/null +++ b/web/src/components/ui/relative-time.tsx @@ -0,0 +1,32 @@ +'use client' + +import { useState, useEffect } from 'react' +import { formatRelativeTime } from '@/lib/date-utils' + +interface RelativeTimeProps { + date: string +} + +export function RelativeTime({ date }: RelativeTimeProps) { + const [isClient, setIsClient] = useState(false) + const [relativeTime, setRelativeTime] = useState('') + + useEffect(() => { + setIsClient(true) + setRelativeTime(formatRelativeTime(date)) + + // Update every minute to keep relative time fresh + const interval = setInterval(() => { + setRelativeTime(formatRelativeTime(date)) + }, 60000) + + return () => clearInterval(interval) + }, [date]) + + // Show absolute date on server, relative time on client + if (!isClient) { + return <>{new Date(date).toLocaleDateString()} + } + + return <>{relativeTime} +}