The School type filter split state schools into "academy or free school" and "council-run". The two were near-halves of one pool (11,186 and 9,316 schools), so choosing one rarely narrowed anything, and the split did not follow the difference a parent feels most, admissions: voluntary aided and foundation schools set their own, as academies do. Faith, which voluntary aided mostly meant, has its own filter. They are now one group, "State school (free)", leaving five. The old keys academy and council resolve to state, so a link made with them keeps working instead of falling through to the raw-label path and returning nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SchoolCompare frontend and CMS
Next.js App Router with React, TypeScript, CSS Modules, Chart.js, Leaflet and Payload CMS. It serves school search, comparisons, rankings, school/place detail pages and editorial content across England.
Start with the repository overview, architecture and development checks.
Source map
| Path | Purpose |
|---|---|
app/(frontend)/ |
Public root layout, server pages and FastAPI proxy |
app/(payload)/ |
Payload root layout, /admin and /cms-api |
app/robots.ts, app/opengraph-image.tsx, root icons |
Site-wide metadata endpoints |
components/ |
Client views and reusable display components |
components/school/ |
School detail sections |
lib/api.ts, lib/types.ts |
Fetch wrappers and manual school API types |
lib/schoolSections.ts, lib/compareLogic.ts |
Presentation decisions and data preparation |
context/, hooks/ |
Comparison state, suggestion state and responsive behaviour |
collections/, blocks/, migrations/ |
CMS schema and production migrations |
__tests__/ |
Jest and React Testing Library tests |
Do not introduce a shared app/layout.tsx: public pages and Payload have separate
root layouts. Keep root metadata files outside the route groups.
Data and state
Server pages fetch initial data directly from FASTAPI_URL. Browser fetches use
/api by default, forwarded by app/(frontend)/api/[...path]/route.ts.
FASTAPI_URL must include /api. See .env.example for CMS and API settings.
State uses React hooks/context, URL search parameters and localStorage for the comparison basket. SWR is not installed. Maps use dynamic Leaflet wrappers. Revalidation intervals are configured in fetch wrappers and pages; they vary by resource. Backend reloads do not automatically invalidate every Next.js cache.
Commands
npm ci
npm run typecheck
npm test -- --runInBand
npm run build
test:watch and test:coverage are also available. There is no lint script.
A running application needs the backend/data environment described in the
development guide.
After CMS field or editor changes, run npm run generate:importmap. Keep
payload-types.ts generated from the CMS schema rather than editing it by hand.
The build must work without a database connection; avoid module-scope CMS queries
and DB-backed generateStaticParams functions.
See publishing for CMS operations and deployment for staging and production promotion.