refactor(app): move site routes into a (frontend) route group
Payload's admin panel ships its own root layout rendering html/body. Next allows multiple root layouts only when no app/layout.tsx exists, so the site's routes move into their own group. Route groups are invisible to routing: every public URL is unchanged, verified against the build's route table. The metadata file conventions deliberately stay at the app/ root. Moving them into the group renamed /icon.png to /icon-4usi79.png (likewise apple-icon and opengraph-image) and dropped /robots.txt altogether, which would have broken the /icon.png cache-control rule, the outputFileTracingIncludes entry for the share card, and robots.txt. darkThemeSafety reads app/globals.css off disk rather than importing it, so it needed its own path fix — a grep for import specifiers misses it, and it fails as an unrunnable suite rather than a failed assertion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YmbBhr8s7GusjDE12hrZM
This commit is contained in:
1 parent
eb648f3f76
commit
2437ffce42
21 files changed
+57
-26
No files matched your search
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Rankings Page (SSR)
|
||||
* Display top-ranked schools by various metrics
|
||||
*/
|
||||
|
||||
import { fetchRankings, fetchFilters, fetchMetrics } from '@/lib/api';
|
||||
import { RankingsView } from '@/components/RankingsView';
|
||||
import { absoluteUrl } from '@/lib/site';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
interface RankingsPageProps {
|
||||
searchParams: Promise<{
|
||||
metric?: string;
|
||||
local_authority?: string;
|
||||
year?: string;
|
||||
phase?: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
// 'School Rankings' matched nothing anyone types. League tables is the
|
||||
// phrase parents actually search, and it spikes each results day.
|
||||
title: { absolute: 'Primary & Secondary School League Tables | schoolcompare' },
|
||||
description:
|
||||
'Rank English schools by SATs results, GCSEs, Progress 8 or Attainment 8, and filter by local authority or year. Built from the DfE’s own figures.',
|
||||
keywords: 'school rankings, top schools, best schools, KS2 rankings, KS4 rankings, school league tables',
|
||||
// Param forms (?metric=&local_authority=&year=&phase=) collapse here for
|
||||
// now. W3 replaces them with real indexable paths.
|
||||
alternates: { canonical: absoluteUrl('/rankings') },
|
||||
};
|
||||
|
||||
// Dynamic via searchParams; remove force-dynamic so internal data fetches
|
||||
// can still use Next.js's per-call revalidate cache.
|
||||
|
||||
export default async function RankingsPage({ searchParams }: RankingsPageProps) {
|
||||
const { metric: metricParam, local_authority, year: yearParam, phase: phaseParam } = await searchParams;
|
||||
|
||||
const phase = phaseParam || 'primary';
|
||||
const metric = metricParam || (phase === 'secondary' ? 'attainment_8_score' : 'rwm_expected_pct');
|
||||
const year = yearParam ? parseInt(yearParam) : undefined;
|
||||
|
||||
// Fetch rankings data with error handling
|
||||
try {
|
||||
const [rankingsResponse, filtersResponse, metricsResponse] = await Promise.all([
|
||||
fetchRankings({
|
||||
metric,
|
||||
local_authority,
|
||||
year,
|
||||
limit: 100,
|
||||
phase,
|
||||
}),
|
||||
fetchFilters(),
|
||||
fetchMetrics(),
|
||||
]);
|
||||
|
||||
// Metrics is already an array
|
||||
const metricsArray = metricsResponse?.metrics || [];
|
||||
|
||||
return (
|
||||
<RankingsView
|
||||
rankings={rankingsResponse?.rankings || []}
|
||||
filters={filtersResponse || { local_authorities: [], school_types: [], years: [], phases: [], genders: [], admissions_policies: [] }}
|
||||
metrics={metricsArray}
|
||||
selectedMetric={metric}
|
||||
selectedArea={local_authority}
|
||||
selectedYear={year}
|
||||
selectedPhase={phase}
|
||||
/>
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error fetching data for rankings page:', error);
|
||||
|
||||
// Return error state with empty data
|
||||
return (
|
||||
<RankingsView
|
||||
rankings={[]}
|
||||
filters={{ local_authorities: [], school_types: [], years: [], phases: [], genders: [], admissions_policies: [] }}
|
||||
metrics={[]}
|
||||
selectedMetric={metric}
|
||||
selectedArea={local_authority}
|
||||
selectedYear={year}
|
||||
selectedPhase={phase}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user