Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions web/src/app/api/agents/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -251,7 +251,7 @@ const getCachedAgents = unstable_cache(
},
['agents-data'],
{
revalidate: 60,
revalidate: 60 * 10, // Cache for 10 minutes
tags: ['agents'],
}
)
Expand All @@ -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')
Expand Down
16 changes: 6 additions & 10 deletions web/src/app/store/page.tsx
Original file line number Diff line number Diff line change
@@ -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'

Expand Down Expand Up @@ -84,29 +82,27 @@ 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 (
<Suspense fallback={<StorePageSkeleton />}>
<AgentStoreClient
initialAgents={agentsData}
initialPublishers={userPublishers}
session={session}
session={null} // Client will handle session
searchParams={searchParams}
/>
</Suspense>
Expand Down
10 changes: 7 additions & 3 deletions web/src/app/store/store-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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'
Expand Down Expand Up @@ -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) || ''
)
Expand Down Expand Up @@ -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 <RelativeTime date={agent.last_used} />
</span>
)}
</div>
Expand Down
32 changes: 32 additions & 0 deletions web/src/components/ui/relative-time.tsx
Original file line number Diff line number Diff line change
@@ -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}</>
}