---
title: "Route first-load JS over budget (from `.next` build output) (lint/route-js-budget)"
description: "lint/route-js-budget: First-load JS is downloaded, parsed and executed before the page becomes interactive."
canonical: https://void-design.vercel.app/rules/lint/route-js-budget
lastModified: 2026-09-16
---

# Route first-load JS over budget (from `.next` build output)

`lint/route-js-budget` · severity **warn** · category Lint · detected by `void lint` and `void audit`

## Why it matters

First-load JS is downloaded, parsed and executed before the page becomes interactive. Above ~170 KB gzip on marketing routes, mid-range phones on slow networks see multi-second TBT/INP; the Next 16 framework alone is ~133 KB.

## How to fix it

Find what the route pulls in (`next experimental-analyze`), move work to Server Components, dynamic-import below-the-fold widgets and drop heavy client deps. Budget: marketing ≤170 KB, app ≤300 KB gzip (configurable via `budgets.mobile.jsKb`).

## Example

```tsx
const Chart = dynamic(() => import('./chart'), { loading: () => <ChartSkeleton /> })
```

## References

- https://nextjs.org/docs/app/guides/package-bundling
- https://infrequently.org/2025/11/performance-inequality-gap-2026/

## More lint rules

`void lint` reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.

- `jsonld-missing` No JSON-LD structured data — [lint/jsonld-missing](https://void-design.vercel.app/rules/lint/jsonld-missing)
- `sitemap-lastmod-now` Sitemap uses `new Date()` for `lastModified` — [lint/sitemap-lastmod-now](https://void-design.vercel.app/rules/lint/sitemap-lastmod-now)
- `multiple-h1` More than one `<h1>` in a route's page + layouts — [lint/multiple-h1](https://void-design.vercel.app/rules/lint/multiple-h1)
- `jsonld-deprecated-type` JSON-LD type that no longer produces rich results — [lint/jsonld-deprecated-type](https://void-design.vercel.app/rules/lint/jsonld-deprecated-type)
- `animate-undefined` `animate-*` class with no matching `--animate-*` theme variable or `@keyframes` — [lint/animate-undefined](https://void-design.vercel.app/rules/lint/animate-undefined)
- `random-in-render` `Math.random()` / `Date.now()` / `new Date()` evaluated in a component render body — [lint/random-in-render](https://void-design.vercel.app/rules/lint/random-in-render)
- `duplicate-children-not-hidden` Children repeated for a marquee/loop without `aria-hidden` or `inert` on the copies — [lint/duplicate-children-not-hidden](https://void-design.vercel.app/rules/lint/duplicate-children-not-hidden)
- `conditional-hook` Hook called inside a JSX expression, `&&`, ternary or callback — [lint/conditional-hook](https://void-design.vercel.app/rules/lint/conditional-hook)

Detected by `void lint` and `void audit`. Explain it in a terminal: `void rules lint/route-js-budget`
