Commit Graph
7 Commits
Author SHA1 Message Date
TudorandClaude Opus 4.8 9556595800 feat(security): allow analytics subdomain to iframe the site
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 48s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 8s
Replace X-Frame-Options: SAMEORIGIN with a CSP frame-ancestors directive
so analytics.schoolcompare.co.uk (Umami heatmap/recorder) can embed the
site while all other origins stay blocked. X-Frame-Options cannot allow a
specific sibling subdomain (ALLOW-FROM is deprecated/ignored by modern
browsers), so frame-ancestors is the correct replacement.

Also update the nginx snippet in DEPLOYMENT.md to match, so the reverse
proxy doesn't re-inject a conflicting X-Frame-Options header.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 22:50:44 +01:00
TudorandClaude Fable 5 95a5783da1 fix(frontend): proxy /api and /sitemap.xml at runtime, not via baked rewrites
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 9m38s
PR Checks / Backend Smoke (pull_request) Successful in 5s
PR Checks / Build Backend (no push) (pull_request) Successful in 10s
PR Checks / Build Frontend (no push) (pull_request) Successful in 50s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 3m13s
next.config.js rewrites() bakes its destination into the build
(routes-manifest.json), capturing FASTAPI_URL at build time. Because one
frontend image is promoted staging->prod, the baked backend host forced
every environment to name the backend service identically; staging names
it 'backend_stg', so the browser's /api/* calls proxied to the baked
'http://backend' and failed with getaddrinfo ENOTFOUND backend. (SSR was
unaffected because lib/api.ts reads FASTAPI_URL at runtime.)

Replace the rewrites with route handlers that read FASTAPI_URL per
request:
- app/api/[...path]/route.ts — transparent proxy for all methods, streams
  the response, strips hop-by-hop headers, and returns 502 on upstream
  failure instead of crashing.
- app/sitemap.xml/route.ts — proxies the backend sitemap (robots.ts points
  crawlers here).

The same promoted image now adapts to whatever the backend is called in
each environment. Verified: production build succeeds with /api/[...path]
and /sitemap.xml as dynamic routes and an empty rewrites manifest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 10:00:42 +01:00
Tudor SitaruandClaude Opus 4.7 62eeee5f7c perf: cache aggressively and trim client bundle
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 1m1s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 53s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 2m4s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Frontend
- Dynamic-import Chart.js components on detail/compare views so Chart.js
  no longer ships in initial JS.
- Drop force-dynamic on home, compare, rankings so internal data fetches
  reuse Next.js's per-call revalidate cache.
- Switch /school/[slug] to ISR with a 7-day revalidate window (school
  data updates annually).
- Preconnect to analytics + postcodes.io; remove redundant defer on the
  Umami Script tag (afterInteractive already covers it).
- Bump images.minimumCacheTTL to 1 year.
- Extract HowItWorks and Editorial sections as server components passed
  to HomeView via slot props so their JSX stays out of the client bundle.

Backend
- Add GZipMiddleware (min 512 bytes).
- Add CacheAndETagMiddleware: per-path Cache-Control with long s-maxage
  + stale-while-revalidate, ETag generation, and 304 on If-None-Match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-02 13:46:45 +01:00
tudorandClaude Sonnet 4.6 b7bff7bf6b feat(seo): static sitemap generation job via Airflow
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 45s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m5s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m29s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
- Backend builds sitemap.xml from school data at startup (in-memory)
- POST /api/admin/regenerate-sitemap refreshes it after data updates
- New Airflow DAG (sitemap_generate) runs Sundays 05:00 and calls the endpoint
- Next.js proxies /sitemap.xml to the backend; removes the slow dynamic sitemap.ts
- docker-compose passes BACKEND_URL + ADMIN_API_KEY to Airflow env

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 15:15:41 +01:00
tudorandClaude Opus 4.6 6315f366c8 fix(build): single-brace JSX for schoolUrl, migrate images.domains to remotePatterns
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 32s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m10s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 32s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 14:15:06 +01:00
TudorandClaude Opus 4.5 53e11aca82 Fix: Append :path* to FASTAPI_URL in rewrites
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 35s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m11s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
The rewrite destination was using FASTAPI_URL directly, which
replaced the entire destination including the :path* parameter.
This caused /api/compare to rewrite to just http://backend:80/api
instead of http://backend:80/api/compare.

Now properly constructs: ${FASTAPI_URL}/:path*

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 11:00:18 +00:00
TudorandClaude Sonnet 4.5 ff7f5487e6 Complete Next.js migration with SSR and Docker deployment
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 1m26s
Build and Push Docker Images / Build Frontend (Next.js) (push) Failing after 1m48s
Build and Push Docker Images / Trigger Portainer Update (push) Has been skipped
- Migrate from vanilla JavaScript SPA to Next.js 16 with App Router
- Add server-side rendering for all pages (Home, Compare, Rankings)
- Create individual school pages with dynamic routing (/school/[urn])
- Implement Chart.js and Leaflet map integrations
- Add comprehensive SEO with sitemap, robots.txt, and JSON-LD
- Set up Docker multi-service architecture (PostgreSQL, FastAPI, Next.js)
- Update CI/CD pipeline to build both backend and frontend images
- Fix Dockerfile to include devDependencies for TypeScript compilation
- Add Jest testing configuration
- Implement performance optimizations (code splitting, caching)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-02 20:34:35 +00:00