import type { Metadata } from 'next'; import HeroSection from './components/HeroSection'; import NextEventSectionWrapper from './components/NextEventSectionWrapper'; import AboutSection from './components/AboutSection'; import MediaCarouselSection from './components/MediaCarouselSection'; import NewsletterSection from './components/NewsletterSection'; import HomepageFaqSection from './components/HomepageFaqSection'; import { getCarouselImages } from '@/lib/carouselImages'; const siteUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://spanglish.com.py'; const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001'; interface NextEvent { id: string; title: string; titleEs?: string; description: string; descriptionEs?: string; shortDescription?: string; shortDescriptionEs?: string; startDatetime: string; endDatetime?: string; location: string; locationUrl?: string; price: number; currency: string; capacity: number; status: 'draft' | 'published' | 'cancelled' | 'completed' | 'archived'; bannerUrl?: string; externalBookingEnabled?: boolean; externalBookingUrl?: string; availableSeats?: number; bookedCount?: number; isFeatured?: boolean; createdAt: string; updatedAt: string; } async function getNextUpcomingEvent(): Promise { try { const response = await fetch(`${apiUrl}/api/events/next/upcoming`, { next: { tags: ['next-event'] }, }); if (!response.ok) return null; const data = await response.json(); return data.event || null; } catch { return null; } } // Dynamic metadata with next event date for AI crawlers and SEO export async function generateMetadata(): Promise { const event = await getNextUpcomingEvent(); if (!event) { return { title: 'Spanglish – Language Exchange Events in Asunción', description: 'Practice English and Spanish at relaxed social events in Asunción. Meet locals and internationals. Join the next Spanglish meetup.', }; } const eventDate = new Date(event.startDatetime).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric', timeZone: 'America/Asuncion', }); const description = `Next event: ${eventDate} – ${event.title}. Practice English and Spanish at relaxed social events in Asunción. Meet locals and internationals.`; return { title: 'Spanglish – Language Exchange Events in Asunción', description, openGraph: { title: 'Spanglish – Language Exchange Events in Asunción', description, url: siteUrl, siteName: 'Spanglish', type: 'website', images: [ { url: event.bannerUrl ? event.bannerUrl.startsWith('http') ? event.bannerUrl : `${siteUrl}${event.bannerUrl}` : `${siteUrl}/images/og-image.jpg`, width: 1200, height: 630, alt: `Spanglish – ${event.title}`, }, ], }, twitter: { card: 'summary_large_image', title: 'Spanglish – Language Exchange Events in Asunción', description, }, }; } function generateNextEventJsonLd(event: NextEvent) { return { '@context': 'https://schema.org', '@type': 'Event', name: event.title, description: event.shortDescription || event.description, startDate: event.startDatetime, endDate: event.endDatetime || event.startDatetime, eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode', eventStatus: event.status === 'cancelled' ? 'https://schema.org/EventCancelled' : 'https://schema.org/EventScheduled', location: { '@type': 'Place', name: event.location, address: { '@type': 'PostalAddress', addressLocality: 'Asunción', addressCountry: 'PY', }, }, organizer: { '@type': 'Organization', name: 'Spanglish', url: siteUrl, }, offers: { '@type': 'Offer', price: event.price, priceCurrency: event.currency, availability: (event.availableSeats ?? 0) > 0 ? 'https://schema.org/InStock' : 'https://schema.org/SoldOut', url: `${siteUrl}/events/${event.id}`, }, image: event.bannerUrl || `${siteUrl}/images/og-image.jpg`, url: `${siteUrl}/events/${event.id}`, }; } export default async function HomePage() { const carouselImages = getCarouselImages(); const nextEvent = await getNextUpcomingEvent(); return ( <> {nextEvent && (