Files
school_compare/nextjs-app
TudorandClaude Opus 5 180d6e9b3e
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m14s
PR Checks / Backend Smoke (pull_request) Successful in 10s
PR Checks / Build Backend (no push) (pull_request) Successful in 17s
PR Checks / Build Frontend (no push) (pull_request) Successful in 1m19s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 11s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 37s
fix(web): lift the jump sheet above the bottom tab bar
On mobile the last item in "Jump to section" was painted over by the fixed
bottom tab bar and could not be tapped. Reported as nearby schools missing
from the menu; it was there, underneath the bar.

The sticky nav sets `position: sticky` with `z-index: 10`, which makes it a
stacking context. The sheet's own `z-index: 1600` therefore orders it only
inside that context — against the tab bar (z-index 1000) the nav's 10 is what
counts, so the bar wins. Verified on staging: every menu item returns itself
from elementFromPoint except the last, which returns the tab bar.

Latent rather than new. With five sections the list stopped just above the bar;
"Nearby schools" made six, and the sixth is the first to reach it. Any section
added later would have done the same.

Lifted only while the sheet is open, and only to 1100 — above the bar, below
the comparison toast (2000), the fullscreen map (5000) and the info popover
(9999). The backdrop rises with it, so tapping over the bar now dismisses the
sheet instead of navigating away.

The journey asks what a thumb asks: for each item, whether it is the topmost
element at its own centre. A bounding-box check cannot see this — the item is
in the viewport and the right size, just underneath something. Confirmed to
fail against current staging, naming "Nearby schools", before the fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 20:35:25 +01:00
..

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.