Merge pull request 'fix(home): correct education/Ofsted claims on the landing page' (#73) from fix/homepage-education-accuracy into main
Stage (build -> staging -> E2E gate) / Build Backend (FastAPI) (push) Successful in 14s
Stage (build -> staging -> E2E gate) / Build Frontend (Next.js) (push) Successful in 51s
Stage (build -> staging -> E2E gate) / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 14s
Stage (build -> staging -> E2E gate) / Deploy to Staging (push) Successful in 1s
Stage (build -> staging -> E2E gate) / E2E Journeys against Staging (push) Successful in 43s

Reviewed-on: #73
This commit was merged in pull request #73.
This commit is contained in:
2026-07-21 09:04:57 +00:00
4 changed files with 109 additions and 35 deletions
+5 -5
View File
@@ -13,17 +13,17 @@ export function EditorialSection({ totalSchools, localAuthorityCount }: Editoria
<div className={styles.editorialGrid}> <div className={styles.editorialGrid}>
<div className={styles.editorialText}> <div className={styles.editorialText}>
<div className={styles.editorialKicker}>About school data</div> <div className={styles.editorialKicker}>About school data</div>
<h2 className={styles.editorialHeading}>Making UK school performance data actually readable</h2> <h2 className={styles.editorialHeading}>Making England&apos;s school performance data actually readable</h2>
<p> <p>
School performance data in England is rich but fragmented. The Department for Education publishes School performance data in England is rich but fragmented. The Department for Education and Ofsted
Key Stage 2 SATs, GCSE attainment, Ofsted outcomes, progress scores, admissions figures and publish Key Stage 2 SATs, GCSE attainment, inspection outcomes, progress scores, admissions figures
demographics each in its own table, each with its own jargon. and demographics each in its own table, each with its own jargon.
</p> </p>
<p> <p>
SchoolCompare brings it all into one place. Every school page shows performance against the national SchoolCompare brings it all into one place. Every school page shows performance against the national
average, explains what the numbers mean, and lets you shortlist schools side by side. Built for average, explains what the numbers mean, and lets you shortlist schools side by side. Built for
parents, governors, journalists, and anyone who wants to understand a school without reading a parents, governors, journalists, and anyone who wants to understand a school without reading a
40-page inspection report. full inspection report.
</p> </p>
</div> </div>
<div className={styles.factbox}> <div className={styles.factbox}>
+66 -14
View File
@@ -720,10 +720,13 @@
.miniRowHead { .miniRowHead {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 0.48rem; align-items: baseline;
gap: 0.2rem;
font-size: 0.44rem;
color: var(--text-muted, #6d685f); color: var(--text-muted, #6d685f);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.04em; letter-spacing: 0.01em;
white-space: nowrap;
} }
.miniRowHead strong { .miniRowHead strong {
@@ -869,28 +872,77 @@
color: var(--text-primary, #1a1612); color: var(--text-primary, #1a1612);
} }
.ofstedBadge { .ofstedFramework {
align-self: flex-start; align-self: flex-start;
padding: 0.2rem 0.55rem; padding: 0.15rem 0.5rem;
border-radius: 4px; border-radius: 4px;
background: rgba(45, 125, 125, 0.12); background: rgba(90, 58, 110, 0.12);
color: var(--accent-teal, #2d7d7d); color: #5a3a6e;
font-size: 0.55rem; font-size: 0.5rem;
font-weight: 700; font-weight: 700;
letter-spacing: 0.05em; letter-spacing: 0.05em;
text-transform: uppercase;
} }
.ofstedVerdict { .rcList {
font-family: var(--font-playfair), 'Playfair Display', serif; display: flex;
font-size: 1.05rem; flex-direction: column;
gap: 0.3rem;
}
.rcRow {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.rcArea {
font-size: 0.62rem;
color: var(--text-secondary, #4a453d);
}
.rcChip {
padding: 0.1rem 0.4rem;
border-radius: 3px;
font-size: 0.52rem;
font-weight: 700; font-weight: 700;
line-height: 1.2; letter-spacing: 0.03em;
color: var(--text-primary, #1a1612); white-space: nowrap;
flex-shrink: 0;
} }
.ofstedVerdict em { .rcChipGood {
background: rgba(45, 125, 125, 0.12);
color: var(--accent-teal, #2d7d7d); color: var(--accent-teal, #2d7d7d);
font-style: normal; }
.rcChipNeutral {
background: var(--accent-gold-bg, rgba(180, 150, 40, 0.12));
color: var(--accent-gold-text, #7a6800);
}
/* Safeguarding is a separate binary met/not-met judgement, not a graded area,
so it sits below the five-point list behind a divider with its own chip. */
.rcSafeguarding {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
margin-top: 0.05rem;
padding-top: 0.35rem;
border-top: 1px dashed var(--border-color, #e5dfd5);
}
.rcSep {
color: var(--text-muted, #8a847a);
font-style: italic;
}
.rcChipMet {
background: transparent;
color: var(--accent-teal, #2d7d7d);
border: 1px solid rgba(45, 125, 125, 0.4);
} }
.ofstedMeta { .ofstedMeta {
+1 -1
View File
@@ -261,7 +261,7 @@ export function HomeView({ initialSchools, filters, totalSchools, howItWorks, ed
<div className={styles.heroSection}> <div className={styles.heroSection}>
<span className={styles.heroEyebrow}> <span className={styles.heroEyebrow}>
<span className={styles.heroEyebrowDot} aria-hidden="true" /> <span className={styles.heroEyebrowDot} aria-hidden="true" />
Updated with 2026/2027 admissions results Updated for the 2026/27 admissions round
</span> </span>
<h1 className={styles.heroTitle}> <h1 className={styles.heroTitle}>
Every school in England, <em className={styles.heroEmph}>compared.</em> Every school in England, <em className={styles.heroEmph}>compared.</em>
+37 -15
View File
@@ -5,15 +5,26 @@
import styles from './HomeView.module.css'; import styles from './HomeView.module.css';
export function HowItWorksSection() { export function HowItWorksSection() {
// "exc" is the school's above-expected result. DfE names this differently
// by subject: "higher standard" for the reading and maths tests, "greater
// depth" for teacher-assessed writing. "nat" is the national expected %.
const miniCascade = [ const miniCascade = [
{ subj: 'Reading', exp: 96, exc: 73, nat: 75 }, { subj: 'Reading', exp: 96, exc: 44, nat: 75, excLabel: 'Higher std' },
{ subj: 'Writing', exp: 81, exc: 15, nat: 72 }, { subj: 'Writing', exp: 81, exc: 26, nat: 72, excLabel: 'Greater depth' },
{ subj: 'Maths', exp: 85, exc: 47, nat: 74 }, { subj: 'Maths', exp: 85, exc: 41, nat: 74, excLabel: 'Higher std' },
]; ];
const compareRows = [ const compareRows = [
{ label: 'Reading, Writing & Maths', a: '70%', b: '64%', aHi: true }, { label: 'Reading, Writing & Maths', a: '70%', b: '64%', aHi: true },
{ label: 'Higher standard (RWM)', a: '13%', b: '6%', aHi: true },
{ label: 'Ofsted', a: 'Outstanding', b: 'Good', aHi: true }, { label: 'Ofsted', a: 'Outstanding', b: 'Good', aHi: true },
{ label: 'Reading progress', a: '+2.1', b: '+0.4', aHi: true }, ];
// Report card (Ofsted's framework from Nov 2025): one rating per area of
// school life on a five-point scale. Safeguarding is judged separately, as a
// binary met/not-met outcome — kept out of this list and shown on its own.
const reportCard: Array<{ area: string; grade: string; good: boolean }> = [
{ area: 'Achievement', grade: 'Strong', good: true },
{ area: 'Curriculum & teaching', grade: 'Expected standard', good: false },
{ area: 'Attendance & behaviour', grade: 'Strong', good: true },
]; ];
return ( return (
@@ -29,7 +40,7 @@ export function HowItWorksSection() {
<div className={styles.hiwPhaseBlock}> <div className={styles.hiwPhaseBlock}>
<div className={styles.hiwPhaseLabel}>Primary · Year 6 · <strong>Key Stage 2 SATs</strong></div> <div className={styles.hiwPhaseLabel}>Primary · Year 6 · <strong>Key Stage 2 SATs</strong></div>
<div className={styles.miniCascade}> <div className={styles.miniCascade}>
{miniCascade.map(({ subj, exp, exc, nat }) => ( {miniCascade.map(({ subj, exp, exc, nat, excLabel }) => (
<div key={subj} className={styles.miniCascadeCol}> <div key={subj} className={styles.miniCascadeCol}>
<div className={styles.miniSubj}>{subj}</div> <div className={styles.miniSubj}>{subj}</div>
<div className={styles.miniRowHead}><span>Expected</span><strong>{exp}%</strong></div> <div className={styles.miniRowHead}><span>Expected</span><strong>{exp}%</strong></div>
@@ -37,7 +48,7 @@ export function HowItWorksSection() {
<div className={styles.miniNatPill} style={{ left: `${nat}%` }}>{nat}%</div> <div className={styles.miniNatPill} style={{ left: `${nat}%` }}>{nat}%</div>
<div className={styles.miniBarExp} style={{ width: `${exp}%` }} /> <div className={styles.miniBarExp} style={{ width: `${exp}%` }} />
</div> </div>
<div className={styles.miniRowHead}><span>Exceeding</span><strong>{exc}%</strong></div> <div className={styles.miniRowHead}><span>{excLabel}</span><strong>{exc}%</strong></div>
<div className={styles.miniTrack}> <div className={styles.miniTrack}>
<div className={styles.miniBarExc} style={{ width: `${exc}%` }} /> <div className={styles.miniBarExc} style={{ width: `${exc}%` }} />
</div> </div>
@@ -49,15 +60,15 @@ export function HowItWorksSection() {
<div className={styles.hiwPhaseLabel}>Secondary · Year 11 · <strong>GCSE Attainment 8</strong></div> <div className={styles.hiwPhaseLabel}>Secondary · Year 11 · <strong>GCSE Attainment 8</strong></div>
<div className={styles.att8Row}> <div className={styles.att8Row}>
<div className={styles.att8BarWrap}> <div className={styles.att8BarWrap}>
<div className={styles.att8BarHead}><span>This school</span><span>National avg 50.2</span></div> <div className={styles.att8BarHead}><span>This school</span><span>National avg 45.9</span></div>
<div className={styles.att8Track}> <div className={styles.att8Track}>
<div className={styles.att8Fill} style={{ width: '62%' }} /> <div className={styles.att8Fill} style={{ width: '54.8%' }} />
<div className={styles.att8NatLine} style={{ left: '50%' }} /> <div className={styles.att8NatLine} style={{ left: '45.9%' }} />
</div> </div>
</div> </div>
<div className={styles.att8Score}> <div className={styles.att8Score}>
<div className={styles.att8Value}>62.4</div> <div className={styles.att8Value}>54.8</div>
<div className={styles.att8Delta}>+12.2 vs national</div> <div className={styles.att8Delta}>+8.9 vs national</div>
</div> </div>
</div> </div>
</div> </div>
@@ -77,15 +88,26 @@ export function HowItWorksSection() {
<span className={styles.ofstedBullet} /> <span className={styles.ofstedBullet} />
<span className={styles.ofstedTitle}>Latest Ofsted inspection</span> <span className={styles.ofstedTitle}>Latest Ofsted inspection</span>
</div> </div>
<span className={styles.ofstedBadge}>OUTSTANDING</span> <span className={styles.ofstedFramework}>Report card · five-point scale</span>
<div className={styles.ofstedVerdict}>Rated <em>Outstanding</em> at last inspection.</div> <div className={styles.rcList}>
<div className={styles.ofstedMeta}>Full inspection · March 2024</div> {reportCard.map(({ area, grade, good }) => (
<div key={area} className={styles.rcRow}>
<span className={styles.rcArea}>{area}</span>
<span className={`${styles.rcChip} ${good ? styles.rcChipGood : styles.rcChipNeutral}`}>{grade}</span>
</div>
))}
</div>
<div className={styles.rcSafeguarding}>
<span className={styles.rcArea}>Safeguarding <span className={styles.rcSep}>· separate check</span></span>
<span className={`${styles.rcChip} ${styles.rcChipMet}`}>Met</span>
</div>
<div className={styles.ofstedMeta}>Full inspection · March 2026</div>
</div> </div>
</div> </div>
<div className={styles.hiwCardBody}> <div className={styles.hiwCardBody}>
<div className={styles.hiwStep}>Judgement</div> <div className={styles.hiwStep}>Judgement</div>
<div className={styles.hiwTitle}>Ofsted at a glance</div> <div className={styles.hiwTitle}>Ofsted at a glance</div>
<p className={styles.hiwDesc}>Current grade, inspection date, and a plain-English headline without opening a 40-page report.</p> <p className={styles.hiwDesc}>Since November 2025, Ofsted rates each area of school life on a five-point scale rather than one overall word. We show every area and the inspection date and, for schools not yet reinspected, the older overall grade they still carry.</p>
</div> </div>
</div> </div>