diff --git a/backend/src/db/schema.ts b/backend/src/db/schema.ts index f11f645..2443433 100644 --- a/backend/src/db/schema.ts +++ b/backend/src/db/schema.ts @@ -657,4 +657,4 @@ export type NewSiteSettings = typeof sqliteSiteSettings.$inferInsert; export type LegalPage = typeof sqliteLegalPages.$inferSelect; export type NewLegalPage = typeof sqliteLegalPages.$inferInsert; export type FaqQuestion = typeof sqliteFaqQuestions.$inferSelect; -export type NewFaqQuestion = typeof sqliteFaqQuestions.$inferInsert; +export type NewFaqQuestion = typeof sqliteFaqQuestions.$inferInsert; \ No newline at end of file diff --git a/frontend/src/app/llms.txt/route.ts b/frontend/src/app/llms.txt/route.ts index 4411cf7..35d43ff 100644 --- a/frontend/src/app/llms.txt/route.ts +++ b/frontend/src/app/llms.txt/route.ts @@ -79,6 +79,39 @@ function formatPrice(price: number, currency: string): string { return `${price.toLocaleString()} ${currency}`; } +function formatISODate(dateStr: string): string { + return new Date(dateStr).toLocaleDateString('en-CA', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + timeZone: EVENT_TIMEZONE, + }); +} + +function formatISOTime(dateStr: string): string { + return new Date(dateStr).toLocaleTimeString('en-GB', { + hour: '2-digit', + minute: '2-digit', + hour12: false, + timeZone: EVENT_TIMEZONE, + }); +} + +function getTodayISO(): string { + return new Date().toLocaleDateString('en-CA', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + timeZone: EVENT_TIMEZONE, + }); +} + +function getEventStatus(event: LlmsEvent): string { + if (event.availableSeats !== undefined && event.availableSeats === 0) return 'Sold Out'; + if (event.status === 'published') return 'Available'; + return event.status; +} + async function getHomepageFaqs(): Promise { try { const response = await fetch(`${apiUrl}/api/faq?homepage=true`, { @@ -107,6 +140,15 @@ export async function GET() { // Header lines.push('# Spanglish Community'); lines.push(''); + lines.push('## Metadata'); + lines.push(''); + lines.push('- Type: Event Community'); + lines.push('- Primary Language: English, Spanish'); + lines.push('- Location: Asunción, Paraguay'); + lines.push(`- Time Zone: ${EVENT_TIMEZONE}`); + lines.push(`- Last Updated: ${getTodayISO()}`); + lines.push(`- Canonical URL: ${siteUrl}`); + lines.push(''); lines.push('> English-Spanish language exchange community organizing social events and meetups in Asunción, Paraguay.'); lines.push(''); lines.push(`- Website: ${siteUrl}`); @@ -118,8 +160,8 @@ export async function GET() { const telegram = process.env.NEXT_PUBLIC_TELEGRAM; const email = process.env.NEXT_PUBLIC_EMAIL; - if (instagram) lines.push(`- Instagram: https://instagram.com/${instagram}`); - if (telegram) lines.push(`- Telegram: https://t.me/${telegram}`); + if (instagram) lines.push(`- Instagram: ${instagram}`); + if (telegram) lines.push(`- Telegram: ${telegram}`); if (email) lines.push(`- Email: ${email}`); if (whatsapp) lines.push(`- WhatsApp: ${whatsapp}`); @@ -130,18 +172,25 @@ export async function GET() { lines.push(''); if (nextEvent) { - lines.push(`- Event: ${nextEvent.title}`); - lines.push(`- Date: ${formatEventDate(nextEvent.startDatetime)}`); - lines.push(`- Time: ${formatEventTime(nextEvent.startDatetime)}`); + const status = getEventStatus(nextEvent); + lines.push(`- Event Name: ${nextEvent.title}`); + lines.push(`- Event ID: ${nextEvent.id}`); + lines.push(`- Status: ${status}`); + lines.push(`- Date: ${formatISODate(nextEvent.startDatetime)}`); + lines.push(`- Start Time: ${formatISOTime(nextEvent.startDatetime)}`); if (nextEvent.endDatetime) { - lines.push(`- End time: ${formatEventTime(nextEvent.endDatetime)}`); + lines.push(`- End Time: ${formatISOTime(nextEvent.endDatetime)}`); } - lines.push(`- Location: ${nextEvent.location}, Asunción, Paraguay`); - lines.push(`- Price: ${formatPrice(nextEvent.price, nextEvent.currency)}`); + lines.push(`- Time Zone: ${EVENT_TIMEZONE}`); + lines.push(`- Venue: ${nextEvent.location}`); + lines.push('- City: Asunción'); + lines.push('- Country: Paraguay'); + lines.push(`- Price: ${nextEvent.price === 0 ? 'Free' : nextEvent.price}`); + lines.push(`- Currency: ${nextEvent.currency}`); if (nextEvent.availableSeats !== undefined) { - lines.push(`- Available spots: ${nextEvent.availableSeats}`); + lines.push(`- Capacity Remaining: ${nextEvent.availableSeats}`); } - lines.push(`- Details and tickets: ${siteUrl}/events/${nextEvent.id}`); + lines.push(`- Tickets URL: ${siteUrl}/events/${nextEvent.id}`); if (nextEvent.shortDescription) { lines.push(`- Description: ${nextEvent.shortDescription}`); } @@ -156,12 +205,25 @@ export async function GET() { lines.push('## All Upcoming Events'); lines.push(''); for (const event of upcomingEvents) { + const status = getEventStatus(event); lines.push(`### ${event.title}`); - lines.push(`- Date: ${formatEventDate(event.startDatetime)}`); - lines.push(`- Time: ${formatEventTime(event.startDatetime)}`); - lines.push(`- Location: ${event.location}, Asunción, Paraguay`); - lines.push(`- Price: ${formatPrice(event.price, event.currency)}`); - lines.push(`- Details: ${siteUrl}/events/${event.id}`); + lines.push(`- Event ID: ${event.id}`); + lines.push(`- Status: ${status}`); + lines.push(`- Date: ${formatISODate(event.startDatetime)}`); + lines.push(`- Start Time: ${formatISOTime(event.startDatetime)}`); + if (event.endDatetime) { + lines.push(`- End Time: ${formatISOTime(event.endDatetime)}`); + } + lines.push(`- Time Zone: ${EVENT_TIMEZONE}`); + lines.push(`- Venue: ${event.location}`); + lines.push('- City: Asunción'); + lines.push('- Country: Paraguay'); + lines.push(`- Price: ${event.price === 0 ? 'Free' : event.price}`); + lines.push(`- Currency: ${event.currency}`); + if (event.availableSeats !== undefined) { + lines.push(`- Capacity Remaining: ${event.availableSeats}`); + } + lines.push(`- Tickets URL: ${siteUrl}/events/${event.id}`); lines.push(''); } } @@ -185,6 +247,18 @@ export async function GET() { lines.push(`- More FAQ: ${siteUrl}/faq`); lines.push(''); + // Update Policy + lines.push('## Update Policy'); + lines.push(''); + lines.push('Event information is updated whenever new events are published or ticket availability changes.'); + lines.push(''); + + // AI Summary + lines.push('## AI Summary'); + lines.push(''); + lines.push('Spanglish Community organizes English-Spanish language exchange events in Asunción, Paraguay. Events require registration via the website.'); + lines.push(''); + const content = lines.join('\n'); return new NextResponse(content, {