Skip to main content
crust builds a static map of a Next.js App Router project from source, joins it to the build output, and stores a snapshot per build — so a regression traces back to the commit and the import that caused it.

The failure it exists to catch

Under Cache Components, removing a cache directive deep in a utility silently shrinks the static shell. No build error. No bundle growth. Nothing surfaces it.
The call site named there is three frames below the page, in a file the route never mentions.
Under the older experimental_ppr model a dynamic API outside a Suspense boundary threw a build error, so you found out immediately. Cache Components inverts the default: absence of caching is what postpones, and it fails quietly.

What it does

Analyze

Route table, first-load JS, server/client boundaries, and why each route is dynamic.

Diff

Per-route deltas naming the module responsible, not just the route that grew.

Shell engine

Predicted versus actual static shell, and the call site that broke it.

CI

Budgets on bundle size and shell ratio, with a PR comment that updates in place.

Why not the tools you already have

Route-level regression blame and shell composition, together, is the gap.

Support

Next.js 15 and 16, webpack and Turbopack. Outside that range crust refuses to run rather than emit numbers it cannot stand behind. See support and non-goals.