Skip to content

Technical guide · Core platform

Page status: Active

Public Performance Budgets

NutsNews is mobile-first and image-heavy, so public page speed needs explicit limits. This page defines the current budgets, the CI checks, and the common fixes to use before rais…

Visual overview

Primary diagram

System map

NutsNews is mobile-first and image-heavy, so public page speed needs explicit limits. This page defines the current budgets, the CI checks, and the common fixes to use before rais…

Render the repository-owned system map when you need it.

Diagram is not rendered yet.

View as text
Public Performance Budgets

NutsNews is mobile-first and image-heavy, so public page speed needs explicit limits. This page defines the current budgets, the CI checks, and the common fixes to use before rais…

flowchart TD
  accTitle: Public Performance Budgets
  accDescr {
    NutsNews is mobile-first and image-heavy, so public page speed needs explicit limits. This page defines the current budgets, the CI checks, and the common fixes to use before rais…
  }
  P[PR touches web code] --> B[CI runs npm run test:performance-budget]
  B --> C{Bundle/lighthouse thresholds pass?}
  C -->|no| D[Fail build and upload report]
  C -->|yes| E[Build artifacts remain within budgets]
  E --> F[Deployable PR ready]
  F --> G[Runtime smoke/route checks verify performance posture]
  D --> H[Adjust bundles/images/config and rerun]
  C -->|report generated| I[Lighthouse + route bundle assertions]
  I --> J[Homepage and article detail budgets reviewed]

Public Performance Budgets

Fullscreen diagram view.

NutsNews is mobile-first and image-heavy, so public page speed needs explicit limits. This page defines the current budgets, the CI checks, and the common fixes to use before raising a limit.


Every pull request that changes the web app builds NutsNews and checks public page performance budgets. If JavaScript, CSS, image weight, Lighthouse, or response-time guardrails cross a hard limit, CI fails and uploads a report.

The budget workflow runs npm run test:performance-budget from web/. That command reuses the homepage budget report, adds route bundle checks for the homepage and article detail page, verifies the image optimizer stays bounded, and confirms Lighthouse keeps response-time and Core Web Vitals-style assertions.

The budget layer uses generated Next.js build manifests and route client reference manifests instead of live production traffic for bundle checks. Lighthouse remains the browser-level check for public pages and now includes a server response-time assertion. Budget file changes still require [performance-budget-reviewed] in the PR title or body.

flowchart TD
PR[Web PR or main push] --> Build[Build Next.js app]
Build --> Homepage[Homepage budget script]
Build --> Public[Public route budget script]
Public --> RouteBundles[Homepage and article bundle budgets]
Public --> Images[Image optimizer guardrails]
Public --> Lighthouse[Lighthouse config guardrails]
Homepage --> Report[Performance report artifact]
RouteBundles --> Report
Images --> Report
Lighthouse --> Report
Report --> Gate{Hard limit crossed?}
Gate -- Yes --> Fail[Fail CI with annotations]
Gate -- No --> Pass[Pass with report]

These targets apply to the public homepage route:

/
AreaTargetWarnHard limitChecked by
Largest Contentful Paint2.5 s3.0 s4.0 sLighthouse CI and PageSpeed Insights
Initial JavaScript, gzip180 KB220 KB260 KBHomepage budget script
Initial CSS, gzip30 KB45 KB60 KBHomepage budget script
Homepage static images, raw250 KB350 KB400 KBHomepage budget script
Runtime image transfer200 KB300 KB400 KBLighthouse CI and PageSpeed Insights
Total initial transfer, gzip360 KB450 KB550 KBHomepage budget script

The public route budget script also checks build output for these routes:

/
/articles/[id]
RouteAreaTargetWarnHard limitChecked by
HomepageInitial JavaScript, gzip300 KB330 KB380 KBPublic performance budget script
HomepageInitial CSS, gzip30 KB45 KB60 KBPublic performance budget script
HomepageTotal initial transfer, gzip360 KB450 KB550 KBPublic performance budget script
Article detailInitial JavaScript, gzip300 KB340 KB400 KBPublic performance budget script
Article detailInitial CSS, gzip40 KB56 KB72 KBPublic performance budget script
Article detailTotal initial transfer, gzip400 KB500 KB600 KBPublic performance budget script

Hard limits fail CI. Warning limits create GitHub Actions annotations and should be fixed before the next UI change pushes them into failure territory.

The budget source of truth is:

web/performance-budget.json
web/public-performance-budget.json

The Lighthouse resource budget is:

web/lighthouse-budget.json
web/lighthouserc.js

The homepage budget workflow runs on pull requests and pushes that touch the web app:

.github/workflows/homepage-performance-budget.yml

It does five things:

  1. Builds the Next.js app.
  2. Reads the generated .next manifests for the homepage route.
  3. Reads route client reference manifests for homepage and article detail bundle budgets.
  4. Verifies image optimizer and Lighthouse response-time guardrails.
  5. Writes Markdown and JSON reports to web/reports/performance-budget and uploads them as a GitHub Actions artifact.

Run the same check locally:

Terminal window
cd web
npm run build
npm run test:performance-budget

Create a warning-only report while investigating:

Terminal window
cd web
npm run analyze:homepage:warn
node scripts/public-performance-budget.mjs --warn-only

Budget changes should be rare. They need an intentional PR review because raising a budget can hide a real regression.

If a PR changes either budget file, include this marker in the PR title or body after reviewing the reason:

[performance-budget-reviewed]

Use that marker only when the increase is justified, documented, and safer than reducing the bundle or image weight.


Prefer these fixes first:

  • Keep the homepage mostly server-rendered.
  • Avoid adding new client components unless they are needed for interaction.
  • Move non-critical behavior behind dynamic imports.
  • Avoid adding broad UI/helper libraries for small homepage interactions.
  • Reuse existing components instead of introducing a second implementation.

Prefer these fixes first:

  • Remove unused homepage classes when a layout is replaced.
  • Keep animation and theme styles scoped to the components that use them.
  • Avoid duplicate responsive rules for the same card layout.
  • Prefer one shared card system over multiple visual variants.

Prefer these fixes first:

  • Compress static homepage images before committing them.
  • Keep only the true first-screen image marked as priority.
  • Use next/image sizes that match the rendered card width.
  • Do not increase image quality unless the visual difference is obvious on a phone.
  • Avoid adding large decorative images to the initial viewport.

Prefer these fixes first:

  • Keep the first visible card simple and stable.
  • Avoid layout shifts in the masthead and first article card.
  • Keep the initial homepage data request cache-friendly.
  • Do not block the first paint on analytics, animations, or optional UI.
  • Check mobile Lighthouse output before trusting desktop-only results.

CI uploads these files when the workflow runs:

web/reports/performance-budget/homepage-performance-budget.md
web/reports/performance-budget/homepage-performance-budget.json
web/reports/performance-budget/public-performance-budget.md
web/reports/performance-budget/public-performance-budget.json

The Markdown report is the easiest one to read. The JSON report is better for automation or comparing two runs.