Repository navigation
Add a dashboard for the targeted energy discount results - #2
Conversation
A static Next.js page (Tailwind v4, @policyengine/ui-kit 0.4.0, Recharts) reading pre-computed results exported by `uk-energy-reforms export-dashboard`. It lets readers pick the option (flat, tiered, tiered with passported households on their own income, household-income test, passporting only), the support amounts (RF's, scaled to £2bn, unit rate) and the dataset, and shows cost and reach, gains by decile, poverty, coverage of struggling households, breakdowns by region and household type, income-threshold cliffs, and PolicyEngine's estimates beside the Resolution Foundation's published figures. Path-mounted at /uk/targeted-energy-discount for the policyengine.org multizone. CI lints and builds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Rename the unit-rate schedule to a bill-share discount (parameters, CLI flag, results keys, docs): it discounts annual gas and electricity spend, standing charges included, not pence per kWh, because the microdata carry no kWh. State the departure and record the calibrated rates. - Say that brackets paying the same amount share one rate, so averages match across them combined, not per bracket. - Dead zones use the top earner's marginal rate: 28%, or 20% when the top earner is over State Pension age (no employee NI), and are scaled by the equivalisation factor under the household-income test. - RF family-type comparison rows count benefit units wherever they live and use household-weighted deciles, as RF does; household-level values stay in `extra`. The write-up explains the remaining gaps. - Caveat the Enhanced FRS household total (30.7m against 28.6m and RF's 28m) wherever paired counts appear, and quote cliff figures from Microcosm only. - Drop the unused second_income column and the dashboard/ line from the README layout (the dashboard arrives in #2). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Review at 67ff3a4b (stacked on #1 at 2b6030c4). Local: bun install --frozen-lockfile needs bun ≥ 1.4 (the lockfile is v2; bun 1.3 refuses it, CI's setup-bun honours packageManager), then bun run lint clean and bun run build prerenders the four routes. dashboard/data/results.json is byte-identical to a fresh export-dashboard from analyses/ on #1's head. Every number I traced from data.ts and format.ts back to the receipts is right, the RF tab's page references match the report, and the methodology tab states the bill-share departure, the three-month assessment and the dead-zone rates. The live page shows the same headlines as the receipts (£2.19bn, 12.54m, 43.9 %, −150k / −20k).
On the benchmarks. Ten of the twelve comparison rows sit within a few points of RF and the gaps are explained by the stated method notes. Two are not: couples with children who lose under the individual test (653k / 676k vs 490k) and their poorest-fifth share (54 / 51 % vs 71 %). I've asked on #1 for the definitional fix (net out passporting; one decile basis). Those rows and the pensioner Microcosm figure will move, so this PR regenerates after #1.
Should fix
Dashboard.tsx:263-266says the eFRS effective sample is "about 10 households within £1,000 of each line". It is 10.8 at £24k but 76–85 at £18k; only the top line is thin.- eFRS with "Bill share" is served without the README's "set aside" caveat: recipients fall 13.11m → 12.09m because 14 % of eFRS households with zero electricity spend get £0, the average shows £190 not £175, and the £18k mean drop is £334 against £135. Warn or hide the combination.
- The breakdown tabs'
ShareBarslabel only the total andbreakdownColumnsomits the passported / income-test-only rates, so that split has neither a direct label nor a table view; the body's claim holds for the overview bars but not here.
Nits. Hard-coded prose numbers that go stale on regeneration: "7–10 %" (:172, :447), "about 10" (:263), "about 28m in the report" (:447), the 21 % / 9 % multi-family shares (:456-457). Methodology should say the thresholds are held nominal to 2026-27. No OG image. Add a "bun ≥ 1.4" note for contributors.
Requesting changes for 1–2 and the regeneration after #1; the rest can ride along.
…G image - Per-line small-sample warning on the thresholds tab (effective sample below 30) instead of a blanket Enhanced FRS note. - Warn when the Enhanced FRS is combined with the bill share: households with no recorded energy spend get nothing, so recipients and averages shift. - Breakdown tables show the passported and income-test-only rates. - Household totals, multi-family shares, nominal thresholds and the passporting basis in the prose are computed from the data. - Open Graph image, with metadataBase so its URL carries the base path. - Note that bun 1.4 or later is needed for the v2 lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the dashboard to the stack and shell of PolicyEngine's published UK dashboards (Next 14, Tailwind 3 with design-system tokens, the PolicyEngine header and footer, ?tab= links) and adds what the review asked for: - a 2027-28 year toggle, keeping 2026-27 (which contains January-March 2027, the report's winter) as the default; - a "Your household" tab whose calculator mirrors the reform and is tested against policyengine-uk cases (bun run test, now in CI); - a redesigned reach section: one sentence and one labelled bar per group; - winners and losers and inequality sections; - a Baseline tab (bills by group, data coverage, and the model beside official statistics and other organisations' figures, with links); - a Methodology tab setting out every assumption, including that policyengine-uk 2.100 does not uprate energy spend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Vahid. Addressed at Should fix
Nits. The hard-coded prose numbers are gone: the dataset notes come from the export, and the rest is computed from the data. The methodology says the thresholds are held nominal (the £24,000 test covers 36% / 38% of households in 2026-27 and 35% / 37% in 2027-28). The page has an Open Graph image, and the README has a bun ≥ 1.4 note. Slack notes
Local: |
- Winners and losers, gains by decile and the new poverty-change chart use ports of @policyengine/ui-kit's PEWinnersLosersChart and PEImpactBarChart (same colours, ordering, tooltips and axes as policyengine.org), as the dashboard skill requires. Two small departures, commented in the code: the impact chart's axis runs to the top nice tick so the tallest label is not clipped, and the winners legend moves under the bars on phones. - Reach bars keep their titles and drop the per-bar sentence. - Methodology drops the schedule table and explains the three sets of amounts in plain terms. - Baseline and Methodology state the corrected price-level caveat: both datasets sit at about the same price level (2024-25 vs April-June 2026), and both sit below this winter's cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Correction to the Baseline tab note in my reply above. I said that policyengine-uk 2.100 leaves Microcosm's bills at 2024-25 prices (£1,440) and so understates them. The first half is right: PolicyEngine/policyengine-uk#1868 reverted #1860's CPI uprating, so spend stays at each dataset's stored price level. The conclusion was wrong. Ofgem's typical-use cap averaged £1,678 over 2024-25 against £1,641 in April–June 2026, the Enhanced FRS's price basis. So the two datasets sit at about the same price level, and the gap between their bills is consumption, not price. Both sit below this winter's prices, since the October–December 2026 cap is 17% above April–June 2026, so bill levels and bill-share payments are understated in the scheme years on both. The Baseline and Methodology tabs now say this ( |
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Second pass at 1e1103bf (rebuilt on the published dashboard template; data regenerated). Local with bun 1.4.0: bun install --frozen-lockfile, bun run test 78 pass, bun run build clean; public/data/targeted_energy_discount_results.json is byte-identical to a fresh export from #1's head. The template rebuild is as described (Next 14, Tailwind 3, design-system tokens, PolicyEngine header/footer, ?tab=), the year toggle defaults to 2026-27, the household calculator mirrors the reform correctly (strict £24k, tiers at £18k, NI out of scope, OECD BHC equivalisation with the under-14 weight, passported tier convention, bill share = rate × bill), the thin-sample flag reads each band's ESS against 30, the eFRS bill-share warning is data-driven, the breakdown bars label all three segments with matching table columns, and the hard-coded prose numbers are gone.
Three places where the page drifted from the response:
- The struggling-households sentence and the missed count are gone. After
9ad5e15the reach section shows a split bar with in-segment percentages (hidden below 6 %) and a legend; "86 % get the discount … 0.56m households (14 %) get nothing" no longer appears anywhere on the tab. That missed count is the figure NEF asked for; put the sentence back or add the count to the bar's label. - Methodology's nominal-threshold sentence has no numbers (
MethodologyTab.jsx:136-138); the response says it gives 36 / 38 % and 35 / 37 %. - Bill-share caveat placement: the Microcosm bill-share view has no inline note that its rates are calibrated on 2024-25 prices (only the eFRS-gated warning at
ReformTab.jsx:147); see #1 for the wording.
Smaller: there is no lint script any more (package.json has only test), so CI and the body's "lint clean" don't apply; 32 sources, not 31; next-env.d.ts is not gitignored so a build dirties the tree; the calculator test asserts amounts only, not the eligibility sentence. Not verified here: console errors and the 375px check (no browser).
Regenerate after #1's basis fix; requesting changes for 1–2.
- Reach bars: each title now carries the households that get nothing
("… (4.1m): 0.56m get nothing"), so the missed count is back without
the per-bar sentence.
- Methodology: the nominal-threshold sentence gives the income-test
coverage by year and dataset, read from the data.
- Bill share: an inline note on every dataset gives the gap between the
dataset's price level and the October-December 2026 cap, and the rate
that would match RF's averages at those prices.
- Comparison with the report: RF-basis and policy-count family rows from
#1; rows RF does not publish read "not published" and stay off the dot
plot.
- The household explanation moved to src/lib/explain.js; the calculator
test now checks each case's eligibility route, tested income and
sentence against policyengine-uk (156 tests).
- ESLint (next/core-web-vitals) with a lint script, run in CI;
next-env.d.ts ignored; data regenerated from #1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Vahid. Addressed at
Smaller.
Checked in a local preview. No console errors on the tabs I changed. The bill-share note, missed counts, threshold numbers and report rows render as intended. The 375px check from the last round still holds: no horizontal page scroll, and the winners legend sits under the bars on phones. |
- Data: the page shows Microcosm only. The data toggles are gone, but the
export still carries the Enhanced FRS and ?dataset=efrs_1573 switches
every tab to it for internal use.
- Your household: inputs are a draft; a Calculate button applies them,
with a note when the results are out of date.
- Colours: every single-series chart uses PE chart-1 teal; two-category
splits keep the one PE pairing that passes the dataviz validator
(teal-400 with chart-4), documented in colors.js.
- Charts: the poverty chart, bills by group and the cut-off bands are
horizontal, like the winners, reach and breakdown charts; the ported
impact bar chart gains a horizontal layout. Bills by region, household
type and tenure are sorted by bill.
- Tables under charts are collapsed behind a "Show the numbers" toggle.
- Inequality: Gini to two decimals, the top-10% share as a percentage,
and changes as relative percentages.
- Wording: "lowest income" deciles instead of "poorest"; "in poverty"
instead of "poor".
- Baseline and the comparison with the report are one tab ("Baseline and
comparisons"); old ?tab=report links still land there. The report's
dot plot has gridlines, a 0-100% axis and a caption.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Third pass at febf8211 with bun 1.4.0: bun install --frozen-lockfile, bun run lint (ESLint back, clean), bun run test 156 pass, bun run build clean; next-env.d.ts ignored. All three items closed: each reach bar's title carries the missed count ("… (4.1m): 0.56m get nothing", ReformTab.jsx:379), the methodology sentence reads the coverage figures from the data (MethodologyTab.jsx:149), and the bill-share note gives each dataset's price gap and the winter-matching rate beside the schedule. The comparison tab shows #1's RF-basis and policy rows with "not published" where RF has no figure.
One mechanical thing before merge: the committed data predates #1's last commit (34d21bc, "neutral income-decile wording"). A fresh export from #1's head is identical to public/data/targeted_energy_discount_results.json in every number and differs only in four labels ("four lowest income deciles" / "lowest income fifth") and one not_modelled reason string; calculator.json is identical. Merge #1's branch in once more and regenerate.
Approving; the order is #1 then this, retargeted to main.
…cument the dataset switch Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The poverty chart plots the fall in each group's poverty rate, so its bars run left to right like the other horizontal charts. Two-category splits (reach, region and household type, cut-offs) use chart-3 dark teal with teal-400 instead of dark blue, matching the winners-and-losers chart; segment labels pick dark or white ink by the fill's luminance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
This PR adds a static dashboard that presents the pre-computed results from #1: the reach, cost and distribution of the Resolution Foundation's targeted energy discount options, the baseline they act on, and PolicyEngine's estimates beside the report's published figures. It is built on the template of PolicyEngine's published UK dashboards (the same shell as the electricity VAT cut dashboard). #1 (the reform and analysis) is merged, and this PR now targets
main.Live: https://uk-targeted-energy-discount.vercel.app (redirects to
/uk/targeted-energy-discount).Changes
dashboard/: Next.js 14 (App Router), React 18, Tailwind 3 with@policyengine/design-systemtokens, Recharts and bun, following the published dashboards' layout.?tab=links, section and metric cards, and chart logo./uk/targeted-energy-discountfor the policyengine.org multizone, with a redirect from/for the bare deployment URL. The canonical and Open Graph tags point at the policyengine.org path.Controls:
The page shows the Microcosm dataset. The export also carries the Enhanced FRS, and
?dataset=efrs_1573switches every tab to it for internal use.2026-27 is the default. It runs from April 2026 to March 2027, so it contains January–March 2027, the winter the report proposes; 2027-28 is the following winter.
Tabs:
bun run testchecks 78 cases computed with policyengine-uk: the amount under each option, and the eligibility route, tested income and explanation sentence.Data caveats shown in the page:
Numbers in the prose are read from the data, not typed in.
Data:
dashboard/public/data/targeted_energy_discount_results.jsonandcalculator.jsonare generated byuv run uk-energy-reforms export-dashboardfromanalyses/rf-billing-me-softly. They hold aggregate estimates and synthetic household cases only.Charts:
@policyengine/ui-kit'sPEWinnersLosersChartandPEImpactBarChart, with the same colours, ordering, tooltips and axes as policyengine.org: winners and losers, gains by decile, and poverty change. They are indashboard/src/components/charts/.Deployment:
dashboard/vercel.jsonpins the Next.js preset and the bun commands. The Vercel projectuk-targeted-energy-discount(policy-engine team) is connected to this repository, with root directorydashboardand production branchmain.CI: the
dashboardjob runsbun install --frozen-lockfile,bun run lint(ESLint,next/core-web-vitals),bun run testandbun run build.Testing
bun run lintis clean.bun run testpasses 156 tests: amounts and eligibility routes for 78 calculator cases, against policyengine-uk.bun run buildcompiles and prerenders the page statically.Notes
main, Vercel builds ofmainfail with "Root Directory does not exist", becausemainhas nodashboard/yet. That check is not required, and those failed builds do not replace the production deployment.policyengine-app-v2that serves the dashboard at policyengine.org/uk/targeted-energy-discount.🤖 Generated with Claude Code