feat/schoolcompare-brand
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
accc562b90 |
feat(brand): adopt the schoolcompare identity across the site
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m3s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 13s
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 4m29s
Implements the supplied brand guideline: the pin-and-leaf mark, the lowercase schoolcompare wordmark, Manrope for headings and Inter for everything a person reads a number from, the deep-teal/coral/mustard/sage palette, and the rounder geometry the guideline asks for. The landing hero is rebuilt to the concept: a Sand panel carrying the proposition, the search and a trust line, with the brand landscape bleeding to the panel's right edge, followed by the four value props. Concept vs reality — where the guideline describes something this product does not have, the real feature takes its place and the decision is recorded in a code comment next to it: - The Thriving Score is not implemented. Four of its five sub-scores (pastoral, enrichment, community, facilities) have no source in DfE or Ofsted data, and its band names are Ofsted's own, which would sit beside the real Ofsted grade and be indistinguishable from it. - Guides, About, Favourites and Sign in are not added to the nav — there are no such pages and no accounts system. Rankings and Admissions, which the guideline omits, keep their places because they exist. - The fourth value prop is "Never miss a deadline" rather than "Save & revisit", which would need shortlisting. Two deviations from the supplied swatches, both forced by contrast and both confined to text and fills. Coral #F97360 under a white label measures 2.75:1 against a 4.5 floor, so --action is a darkened #BE3C27 and the original coral survives as --coral for tints, borders and illustration. Mustard #F2C94C is 1.5:1 as text, so --mustard-ink carries labels while --mustard stays exact for fills and rings. Every token clears AA on all three light grounds; Sand is the binding one, so several values sit a step darker than white alone would need. The guideline is light-only, but the site already ships a dark theme, so it is rebuilt from the same tokens rather than dropped. Verified: tsc clean, 159/159 unit tests, production build green, and the generated share card and app icon render from the new mark. The hero and the site chrome were rendered from the compiled CSS and the prerendered markup to confirm Manrope and Inter actually resolve — a font token that silently falls back has shipped here before. |
||
|
|
8ab0ac0a04 |
feat(design): adopt the Cohort identity — new palette, type, mark and dark theme
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 12s
PR Checks / Build Frontend (no push) (pull_request) Successful in 49s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 3m13s
Implements the direction agreed from the identity board: Route C ("Cohort")
with the paper ground from C1, the Schibsted Grotesk / Literata pairing from
C2, and the iris accent from C3. Dark theme is in scope from the start rather
than retrofitted.
The audit found three things wrong beyond taste:
* No brand asset set. og:image was absent entirely, so every link shared into
a class WhatsApp group rendered as a bare grey card. apple-touch-icon pointed
at an SVG, which iOS ignores, and the manifest shipped no PNGs, so Android
installs had no icon. The header mark and the favicon had also drifted into
two different logos.
* No colour discipline. --primary and --trend-down were the same coral, so the
main CTA and "below average" shared a hue. 58 distinct hex values were spread
across component CSS, and the chart palette was still Chart.js's stock demo
colours.
* A dark theme that was declared but never built — themeColor announced a dark
variant with no dark styling behind it.
What changed:
Colour now has exactly three jobs that never borrow each other's hues: brand
(iris) for interactive and identity, status (teal/amber) for above/below a
comparison point, and phase for categories. Teal/amber rather than green/red
keeps the above/below signal readable for every form of colour blindness.
Every chromatic literal in component CSS is now a token, and the JS-painted
surfaces (Chart.js, Leaflet) read the tokens through lib/theme so they follow
the theme instead of ignoring it.
The mark is the five-bar cohort spread — the same object as the distribution
strip inside a school row, built from opacity steps so it inverts cleanly.
components/Logo.tsx is the single source; the favicon, apple-icon and share
card all derive from its geometry.
globals.css drops 123 dead global classes left over from the vanilla-JS app
(only the btn family, .skip-link and .main were still referenced), along with
the noise overlay. It also gains prefers-reduced-motion support, which was
missing entirely, and a type scale so the 54 ad-hoc font sizes have somewhere
to converge.
Verified: tsc clean, 159 unit tests pass, production build succeeds and
prerenders /icon.svg, /apple-icon and /opengraph-image. Three e2e journeys
added for the asset set, the themeColor/background match, and the dark theme
actually repainting — all silent failures that nothing on the page reveals.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
a1fa4fe874 |
fix(a11y): WCAG AA colour contrast across every route (P0.1)
Live axe-core inventory found 13 failing fg/bg pairs (3.12:1 coral text/ fills, 4.0-4.5 teal near-misses, 2.7 gold badge, 1.9 chart-colour text). All replacement values validated ≥4.5:1 against every background they sit on: - --accent-coral-dark deepened to #b04a2e and used for coral text roles (nav active, back/map links, kickers, chips) and coral fills under white text (btn-primary, phase tabs, section-nav compare, chart chips); new --accent-coral-darker #9c3f26 for their hovers. Decorative coral (pins, bars, borders, focus ring) keeps the brand #e07256. - --accent-teal darkened to #296f6f (rankings values, metric rows, ofsted grades, eyebrows all pass). - Ofsted green #3c8c3c→#2f7a2f; off-token gold #b8920e→--accent-gold-text. - Gender-split pink text #b45778→#a04a68; admissions tip numerals to a 3.8:1 muted brown (28px display text). - New CHART_TEXT_COLORS: AA-dark counterparts of the Chart.js series palette for compare-card values (swatch dots keep true series colour). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9133ecdcd4 |
feat(mobile): iOS polish — theme-color, safe-area, dvh, tap-highlight
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 52s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
MOB-19: Add a viewport Viewport export with viewportFit: 'cover' and themeColor entries for light (#faf7f2) / dark (#1a1612), plus the appleWebApp metadata for the home-screen status bar style and title. Manifest's stale #3b82f6 theme_color updated to match brand cream. MOB-20: Apply env(safe-area-inset-*) to the sticky chrome — the top header gets max(padding, inset-left/right) so the logo and tab links clear the notch in landscape; the bottom tab bar already had inset-bottom and now also gets inset-left/right. MOB-21: Replace 100vh with 100dvh in body min-height, modal max-heights, the map view container, and the fullscreen map. Older engines fall back via the duplicated vh declaration. MOB-22: Set -webkit-tap-highlight-color: transparent on body to suppress the iOS Safari grey flash; add a generic touch-pointer :active rule (opacity 0.7) so taps still register visually on plain anchors and bare buttons. Components with their own :active styling are unaffected. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
a5be07ac0f |
fix(nav): keep bottom tab bar flush to visible viewport on iOS Chrome
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 49s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
iOS Chrome (and some Android browsers) auto-hide their URL bar on scroll. This grows the visual viewport without changing the layout viewport, so a position:fixed bar pinned to bottom:0 — which is relative to the layout viewport — appears to float mid-screen with a gap beneath it. Safari masks the bug because its toolbar shrinks rather than fully retracting. Track the delta between the visual and layout viewports via the VisualViewport API and write it to a --mobile-bar-offset CSS var. The bar uses translate3d to apply that offset, which both fixes the gap and enables hardware compositing so it tracks the toolbar animation without flicker. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
2a8ff29ccd |
feat(nav): mobile bottom tab bar and ≥44px logo tap target
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 49s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 56s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 2m6s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
MOB-01: At ≤640px the top inline nav is hidden and replaced by a fixed bottom tab bar (Search / Compare / Rankings / Admissions) with icon + label, 56px tap targets, env(safe-area-inset-bottom) padding, and the Compare count rendered as a badge on the icon. Eliminates horizontal page overflow on every route (docW was 401–429 at vw 390; now docW === vw). MOB-02: Logo link gains a padded hit area so the touch target is ≥44×44 (was 36×36), without resizing the visual mark. ComparisonToast lifted above the new bottom bar on mobile so the two do not stack on top of each other. body gets a bottom padding equal to the bar height + safe-area inset so page content is never hidden. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
8aca0a7a53 |
feat(ui): site-wide UX/UI audit — unified buttons, tokens, accessibility
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 35s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 1m10s
Build and Push Docker Images / Build Integrator (push) Successful in 57s
Build and Push Docker Images / Build Kestra Init (push) Successful in 31s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
- Add shared button system (.btn-primary/secondary/tertiary/active) in globals.css
- Replace 40+ hardcoded rgba() values with design tokens across all CSS modules
- Add skip link, :focus-visible indicators, and ARIA landmarks
- Standardise button labels ("+ Compare" / "✓ Comparing") across all components
- Add collapse/minimize toggle to ComparisonToast
- Fix heading hierarchy (h3→h2 in ComparisonView)
- Add aria-live on search results, aria-label on trend SVGs
- Add "Search" nav link, fix footer empty section, unify max-widths
- Darken --text-muted for WCAG AA compliance (4.6:1 contrast ratio)
- Net reduction of ~180 lines through button style deduplication
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
c0f44cd29d |
Fix header z-index to prevent map overlap when scrolling
Increased header z-index from 100 to 1000 to ensure it stays above Leaflet map elements (which typically use z-index 400-600). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
18964a34a2 |
Add visual polish and micro-interactions for editorial feel
Phase 1 - Critical Fixes: - EmptyState: warm palette, coral button, Playfair Display title - Pagination: design system colors, coral active state - LoadingSkeleton: warm shimmer with coral tint Phase 2 - Signature Patterns: - Navigation: sliding underline hover effect on links - globals.css: increased noise texture opacity for paper feel - RankingsView: alternating row backgrounds - HomeView: decorative coral bar under section headings Phase 3 - Polish: - SchoolCard: SVG trend icons replacing unicode arrows - RankingsView: styled metallic rank badges replacing emoji medals Phase 4 - Micro-interactions: - Navigation badge: pop animation when count changes - HomeView grid: staggered entry animation for cards Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
c2ec067495 |
Apply warm editorial design system across all components
Replace generic blue/gray colors with warm editorial palette: - Navigation: coral active states, branded logo colors - Footer: navy background, gold section titles - FilterBar: coral search button and focus states - SchoolCard: coral left accent on hover, teal/coral buttons - HomeView: gradient hero section, Playfair Display headings - RankingsView: gold top-3 highlights, warm table styling - ComparisonView: teal card borders, coral buttons Consistent use of CSS variables and Playfair Display serif font for headings throughout. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
ff7f5487e6 |
Complete Next.js migration with SSR and Docker deployment
- 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> |