/** * Individual School Page (SSR) * Dynamic route for school details with full SEO optimization * URL format: /school/138267-school-name-here */ import { fetchSchoolDetails } from '@/lib/api'; import { notFound, redirect } from 'next/navigation'; import { SchoolDetailView } from '@/components/SchoolDetailView'; import { SecondarySchoolDetailView } from '@/components/SecondarySchoolDetailView'; import { parseSchoolSlug, schoolUrl } from '@/lib/utils'; import type { Metadata } from 'next'; interface SchoolPageProps { params: Promise<{ slug: string }>; } export async function generateMetadata({ params }: SchoolPageProps): Promise { const { slug } = await params; const urn = parseSchoolSlug(slug); if (!urn || urn < 100000 || urn > 999999) { return { title: 'School Not Found', }; } try { const data = await fetchSchoolDetails(urn); const { school_info } = data; const canonicalPath = schoolUrl(urn, school_info.school_name); const phaseStr = (school_info.phase ?? '').toLowerCase(); const isAllThrough = phaseStr === 'all-through'; const isSecondary = !isAllThrough && ( phaseStr.includes('secondary') || (data.yearly_data ?? []).some((d: any) => d.attainment_8_score != null) ); const la = school_info.local_authority ? ` in ${school_info.local_authority}` : ''; const title = `${school_info.school_name} | ${school_info.local_authority || 'England'}`; const description = isAllThrough ? `View KS2 SATs and GCSE results for ${school_info.school_name}${la}. All-through school covering primary and secondary education.` : isSecondary ? `View GCSE results, Attainment 8, Progress 8 and school statistics for ${school_info.school_name}${la}.` : `View KS2 performance data, results, and statistics for ${school_info.school_name}${la}. Compare reading, writing, and maths results.`; return { title, description, keywords: isAllThrough ? `${school_info.school_name}, KS2 results, GCSE results, all-through school, ${school_info.local_authority}, SATs, Attainment 8` : isSecondary ? `${school_info.school_name}, GCSE results, secondary school, ${school_info.local_authority}, Attainment 8, Progress 8` : `${school_info.school_name}, KS2 results, primary school, ${school_info.local_authority}, school performance, SATs results`, openGraph: { title, description, type: 'website', url: `https://schoolcompare.co.uk${canonicalPath}`, siteName: 'SchoolCompare', }, twitter: { card: 'summary', title, description, }, alternates: { canonical: `https://schoolcompare.co.uk${canonicalPath}`, }, }; } catch { return { title: 'School Not Found', }; } } // Force dynamic rendering export const dynamic = 'force-dynamic'; export default async function SchoolPage({ params }: SchoolPageProps) { const { slug } = await params; const urn = parseSchoolSlug(slug); // Validate URN format if (!urn || urn < 100000 || urn > 999999) { notFound(); } // Fetch school data let data; try { data = await fetchSchoolDetails(urn); } catch (error) { console.error(`Failed to fetch school ${urn}:`, error); notFound(); } const { school_info, yearly_data, absence_data, ofsted, parent_view, census, admissions, sen_detail, phonics, deprivation, finance } = data; // Redirect bare URN to canonical slug URL const canonicalSlug = schoolUrl(urn, school_info.school_name).replace('/school/', ''); if (slug !== canonicalSlug) { redirect(`/school/${canonicalSlug}`); } const phaseStr = (school_info.phase ?? '').toLowerCase(); const isAllThrough = phaseStr === 'all-through'; // All-through schools go to SchoolDetailView (renders both KS2 + KS4 sections). // SecondarySchoolDetailView is KS4-only, so all-through schools would lose SATs data. const isSecondary = !isAllThrough && ( phaseStr.includes('secondary') || yearly_data.some((d: any) => d.attainment_8_score != null) ); // Generate JSON-LD structured data for SEO const structuredData = { '@context': 'https://schema.org', '@type': 'EducationalOrganization', name: school_info.school_name, identifier: school_info.urn.toString(), ...(school_info.address && { address: { '@type': 'PostalAddress', streetAddress: school_info.address, addressLocality: school_info.local_authority || undefined, postalCode: school_info.postcode || undefined, addressCountry: 'GB', }, }), ...(school_info.latitude && school_info.longitude && { geo: { '@type': 'GeoCoordinates', latitude: school_info.latitude, longitude: school_info.longitude, }, }), ...(school_info.school_type && { additionalType: school_info.school_type, }), }; return ( <>