Staging failed on boot with 42P01, relation "payload.users" does not exist. The schema was empty because no migration existed, and the adapter cannot create tables itself: db-postgres/connect.js gates push on NODE_ENV !== 'production', so it is inert in a deployed container regardless of config. The generated migration is schema-qualified to "payload" throughout but does not create that schema — schemaName says where tables go, it does not create anything. It only worked against the throwaway database used to generate it because the schema was created there by hand, so every real environment would have failed on the first statement. CREATE SCHEMA IF NOT EXISTS is hand-added at the top of up(), which makes it exactly the kind of edit a regeneration discards silently; a test asserts it is present and ordered before the first CREATE TABLE. payload-types.ts is now committed rather than ignored. Ignoring it meant CI typechecked against looser types than a developer with a generated copy, which is how a Record<string, unknown> cast passed CI and then failed locally the moment the file appeared. The post page uses the generated Post and Media types instead, and narrows heroImage rather than asserting it, since the field is an id at shallow depth. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017YmbBhr8s7GusjDE12hrZM
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.