Files
school_compare/nextjs-app
TudorandClaude Opus 5 9a1f56c431
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m4s
PR Checks / Backend Smoke (pull_request) Successful in 9s
PR Checks / Build Backend (no push) (pull_request) Successful in 17s
PR Checks / Build Frontend (no push) (pull_request) Successful in 44s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m44s
feat(places): say what each school is, not only how it scored
The location tables carried one column: a percentage. A parent
shortlisting from a town page is asking a different question first —
does it take my child's age, is it a faith school, does it have a
nursery — and the page could not answer any of it.

Primary tables gain Ages, Religious character, Nursery and
Constituency; secondary tables the same minus Nursery, which is a
question about a different intake. An all-through school renders in
both groups, so its nursery shows under primary alone.

The measure moves to the second column rather than the last. Six
columns overflow a phone and .tableWrap turns that into a horizontal
swipe; with the measure last, the one number the page exists for is
the one scrolled off the screen.

Cell rules are the ones the school page already uses, so the two
surfaces cannot disagree about the same school: "Does not apply",
"None" and "Not applicable" all read as no religious character, and
the en-dash age normalisation moves into formatAgeSpan, which
formatAgeRange now delegates to.

Backend: nursery_provision and parliamentary_constituency were not in
the place response. Both are optional GIAS mart columns that
data_loader degrades to NULL, and the `in rows.columns` guard keeps a
mart the pipeline has not rebuilt working.

Also fixes a live bug on the same line: SCHOOL_COLUMNS already ends
with latitude and longitude, and the endpoint concatenated them again,
so pandas dropped one of every duplicated pair and warned "columns are
not unique" on each request. Ordered de-duplication removes the
warning and the silent drop.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FuPUioHpxtaiDNagQvjxyM
2026-08-27 08:49:14 +01:00
..

SchoolCompare Next.js Application

Modern Next.js application for comparing primary school KS2 performance across England.

Features

  • Server-Side Rendering (SSR): Fast initial page loads with pre-rendered content
  • Individual School Pages: Dedicated pages for each school with full SEO optimization
  • Side-by-Side Comparison: Compare up to 5 schools simultaneously
  • School Rankings: Top-performing schools by various metrics
  • Interactive Maps: Leaflet integration for geographic visualization
  • Performance Charts: Chart.js visualizations for historical data
  • Responsive Design: Mobile-first approach with full responsive support
  • SEO Optimized: Dynamic sitemaps, meta tags, and structured data

Tech Stack

  • Framework: Next.js 16 (App Router)
  • Language: TypeScript 5
  • Styling: CSS Modules + CSS Variables
  • State Management: React Context API + URL state
  • Data Fetching: SWR (client-side) + Next.js fetch (server-side)
  • Charts: Chart.js + react-chartjs-2
  • Maps: Leaflet + react-leaflet
  • Testing: Jest + React Testing Library
  • Validation: Zod

Getting Started

Prerequisites

  • Node.js 24+ (using nvm recommended)
  • FastAPI backend running on port 8000

Installation

# Install dependencies
npm install

# Copy environment variables
cp .env.example .env.local

# Update .env.local with your configuration

Development

# Start development server
npm run dev

# Open http://localhost:3000

Building

# Build for production
npm run build

# Start production server
npm start

Testing

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Linting

# Run ESLint
npm run lint

Project Structure

nextjs-app/
├── app/                      # App Router pages
│   ├── layout.tsx           # Root layout
│   ├── page.tsx             # Home page
│   ├── compare/             # Compare page
│   ├── rankings/            # Rankings page
│   ├── school/[urn]/        # Individual school pages
│   ├── sitemap.ts           # Dynamic sitemap
│   └── robots.ts            # Robots.txt
├── components/              # React components
│   ├── SchoolCard.tsx       # School card component
│   ├── FilterBar.tsx        # Search/filter controls
│   ├── ComparisonView.tsx   # Comparison interface
│   ├── RankingsView.tsx     # Rankings table
│   └── ...
├── lib/                     # Utility libraries
│   ├── api.ts              # API client
│   ├── types.ts            # TypeScript types
│   └── utils.ts            # Helper functions
├── hooks/                   # Custom React hooks
├── context/                 # React Context providers
├── styles/                  # Global styles
├── public/                  # Static assets
└── __tests__/              # Test files

Environment Variables

Variable Description Default
NEXT_PUBLIC_API_URL Public API endpoint (client-side) http://localhost:8000/api
FASTAPI_URL Server-side API endpoint http://localhost:8000/api
NODE_ENV Environment mode development

Performance Optimizations

  • Server-Side Rendering: Initial HTML rendered on server
  • Static Generation: Where possible, pages are pre-generated
  • Image Optimization: Next.js Image component with AVIF/WebP support
  • Code Splitting: Automatic route-based code splitting
  • Dynamic Imports: Heavy components loaded on demand
  • API Caching: Configurable revalidation for data fetching
  • Bundle Optimization: Tree shaking and minification
  • Compression: Gzip compression enabled

SEO Features

  • Dynamic Meta Tags: Generated per page with Next.js Metadata API
  • Open Graph: Social media optimization
  • JSON-LD: Structured data for search engines
  • Sitemap: Auto-generated from database
  • Robots.txt: Search engine crawling rules
  • Canonical URLs: Duplicate content prevention

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

Proprietary - SchoolCompare

Support

For issues and questions, please contact the development team.