Drive a Next.js route to instant navigation under Cache Components using a failing Playwright test and an agentic fix loop.
No visual demo for this skill
Tooling or audit guidance without a UI surface to embed.
Skill markdown
# next-cache-components-optimizer
Set up an agentic optimization loop that drives a Next.js route from "not
instant" to "instant" and keeps it there. The loop is test-driven: encode the
goal as a failing `@next/playwright` `instant()` test, work it to green, and
ship the test as the regression guard. Run it once per target route and entry
point. Work the phases P → G in order; each ends in a gate.
Before changing the route, read the bundled **Optimizing the static shell**
guide at
`node_modules/next/dist/docs/01-app/02-guides/optimizing-the-static-shell.md`.
If it is unavailable, use the [online
guide](https://nextjs.org/docs/app/guides/optimizing-the-static-shell). The
guide owns the framework behavior and implementation patterns. This skill owns
the navigation contract, production rig, trustworthy RED-to-GREEN loop,
parity check, differential, and report.
## What is invariant, and what is yours
One thing here is fixed. The rest is yours. Read this before treating any
command, platform, or env var below as a requirement.
- **Invariant: the verification loop.** Maximizing the shell is worthless
unless you can prove it. The proof is an automated check: under a lock that
gates dynamic data, the static shell still commits. RED shows the gap, GREEN
shows it closed, the test ships as the regression guard. It must run on a
production-like build and must not be able to pass vacuously. Stand the loop
up once; every later optimization is then verifiable by construction. The
loop is the deliverable, not any one route.
- **The mechanism: `@next/playwright` `instant()`.** This skill uses
[`instant()`](https://nextjs.org/docs/app/guides/instant-navigation#prevent-regressions-with-e2e-tests)
as a ruler, not a stopwatch (phase A). It comes from
`@next/playwright` (installed alongside `@playwright/test`, on the same
release line as `next`), so it isn't tied to any host. Keep it. Timing a
navigation by hand is too flaky to trust, and is the failure mode this skill
exists to prevent.
- **Yours: the rig.** How you build, deploy, authenticate, configure
Playwright, and loop belongs to your stack, not to this skill. A local
`next build && next start`, a CI/staging container, and a per-push preview
deploy are equally valid rigs; the verdict comes from the build, never the
platform. Phase 0 maps the invariant onto your repo. Read every platform
name, env-var spelling, and command below as an example to translate, not a
requirement.
## Two entry points, two instant UI contracts
A route reaches the user two ways:
- **Initial load (hard navigation)** commits the route's prerendered static
shell; deferred parts stream in behind their loading skeletons (Suspense
fallbacks, `loading.tsx`).
- **Client-side navigation (soft navigation)** reuses shared layouts and
commits the available App Shell for the destination segments that change.
The same implementation patterns can make either entry point instant. The test
differs only in how the navigation is driven ("Driving the navigation in
tests" below), and the available UI can differ because a soft navigation
reuses layouts above the source and destination's divergence point. Guard the
entry point the user named, and both when both matter. See [What "instant"
means](https://nextjs.org/docs/app/guides/instant-navigation#what-instant-means).
This skill is therefore not limited to increasing the direct-load static
shell. It can also fix a non-instant client navigation when caching reusable
work or moving request-time work behind a focused boundary makes the
destination's available App Shell commit immediately. When that App Shell is
already instant and the goal is to fetch additional URL-specific content
before the click, hand off to `next-partial-prefetching-optimizer`.
## Goal
Make the most meaningful available App Shell UI commit immediately, and let
only genuinely request-time work stream afterward. The shipped test
deterministically encodes **present ∧ instant**. **Non-blank** is the additional
bar the workflow enforces by judgment because an `instant()` pass alone is
satisfied by an empty shell.
`instant()` is a ruler, not a stopwatch: assert that the shell appears under
the lock; do not time it. A trustworthy verdict requires a production build
(phase A).
The GREEN under the lock is the deterministic verdict; each gate keeps it
trustworthy.
## Reporting to the user
This loop is meant to run unattended, so it doesn't stop to ask between steps.
Work the navigation the user named, finish it, and stop. What matters is how you
word and present the results, not how often you interrupt. The mechanics below —
the rig, RED, GREEN, the gates — are your scaffolding; the user never needs to
hear those words.
- **Speak their language.** Describe the gap and the result in terms of what the
user sees: "navigating to the dashboard waited on the charts query before
anything painted; now the layout and skeletons paint instantly and the charts
…