How do you improve INP on a Next.js website?
You improve INP on a Next.js website by reducing how much JavaScript runs on the main thread when a visitor taps, clicks or types. In practice that means less hydration, smaller client components, later third-party scripts and event handlers that hand control back to the browser quickly.
Interaction to Next Paint measures how long a page takes to visibly respond to an interaction, and Google's guidance on INP at web.dev treats 200 milliseconds or less as good. It's part of running any of the sites covered in our guide to Next.js for marketing websites, and it's the Core Web Vital most sites fail. If you want the platform-neutral version first, read our guide to how to fix INP.
Why do Next.js sites struggle with INP?
Next.js sites struggle with INP because React has to hydrate the page in the browser, attaching event handlers and rebuilding component state, and that work competes with the visitor's first taps. Add analytics, chat widgets and animation libraries, and the main thread stays busy just when people start interacting.
- Next.js sites passing INP, Q2 2026 field data
- About 2/3
- Median Next.js INP in the same data
- ~236ms
- Google's threshold for good INP
- 200ms
Those first two figures come from Core Web Vitals field data for Q2 2026 in our research. A median above the good threshold means a typical Next.js site is close to failing, and a large share do fail. It doesn't mean Next.js is slow by nature. It means the defaults are easy to undo: one large client component high in the tree, or one heavy script in the root layout, is enough.
Cause | How it hurts INP | Typical fix |
|---|---|---|
Client components high in the tree | Whole sections hydrate and re-render on interaction | Move the client boundary down to the interactive leaf |
Large client bundles | Long parse and hydration tasks during early taps | Dynamic imports for heavy, below-the-fold widgets |
Third-party scripts | Tag managers, chat and heatmaps block the main thread | Load later with next/script, or after first interaction |
Expensive event handlers | Long tasks before the next paint | Show feedback first, defer the rest, use transitions |
Scroll and animation libraries | Main-thread work on every scroll or frame | CSS transforms and compositor-friendly animation |
Very large DOM | Slower style and layout after each update | Trim markup, paginate long lists |
How do you find the interaction that's hurting Next.js INP?
Find the slow interaction with field data before touching code. Lab tools rarely reproduce real INP, because it depends on which elements real visitors use, on real devices, while real scripts are loading.
- Check the Core Web Vitals report in Search Console and your CrUX data to see which page groups fail INP, on mobile and desktop.
- Add the web-vitals library's attribution build to send INP events to your analytics, including the element interacted with and how the time splits between input delay, processing and presentation.
- Group events by element and page. Usually one or two interactions, such as a menu button, an accordion or a pricing toggle, account for most failures.
- Reproduce that interaction in Chrome DevTools with CPU throttling, and record a performance trace to see which scripts run.
- Fix, deploy, and wait for field data to update before declaring victory.
The time split tells you where to look. High input delay means something else was running when the visitor tapped, often hydration or a third-party script. High processing time means your own handler is slow. High presentation delay usually means a large re-render or layout change after the update.
What are the concrete Next.js INP fixes?
The concrete fixes fall into six steps, ordered by how often they solve the problem on marketing sites. Most sites only need the first three.
Push client boundaries down
Keep pages, sections and layouts as Server Components. Put the "use client" directive only on the small piece that needs state or handlers, such as the toggle, not the pricing section around it. Pass server-rendered content into client components as children.
Delay third-party scripts
Audit every script in the root layout and tag manager. Load analytics with next/script using afterInteractive, and non-essential tools like chat, heatmaps and social embeds with lazyOnload or only after the visitor first interacts.
Split heavy widgets
Load calculators, carousels, video players and maps with next/dynamic so their code arrives when needed rather than during hydration.
Make handlers respond first
Update the visible state immediately, then defer analytics calls and expensive work. Wrap non-urgent state updates in startTransition so React keeps the page responsive.
Reduce re-render scope
Avoid putting frequently changing state in a context near the root. Split context, memoize expensive children, or let the React Compiler handle memoization where your setup supports it.
Use compositor-friendly animation
Animate transform and opacity with CSS where possible, avoid scroll listeners that run on every frame, and test smooth-scroll and animation libraries on a mid-range phone.
Images and fonts matter less for INP than for loading metrics, but they compete for the same early main-thread time. Our explainer on next/image, fonts and scripts covers the settings, and our guide to static vs server rendering in Next.js explains why static pages give hydration a head start.
Hypothetical example: fixing a slow pricing toggle
For example, suppose field data shows a SaaS pricing page failing INP on mobile, and attribution points at the monthly and annual billing toggle.
The trace shows two problems. The whole pricing section, including plan descriptions and a comparison table, is one client component, so every toggle re-renders hundreds of elements. And a chat widget and a session-recording script load in the root layout, so taps soon after load wait behind them.
The fix: the section becomes a Server Component; only the toggle and the price figures are a small client component that receives the plan data as props. The chat widget loads after the first scroll or tap, and session recording moves to lazyOnload. No design changed. The team then watches field data for several weeks to confirm the page moves into the good range, rather than trusting a single lab run.
How do you keep Next.js INP good after launch?
Keep Next.js INP good by treating it as an ongoing budget, not a one-time fix. New scripts, new sections and new experiments add main-thread work every month, and INP regressions arrive quietly through the tag manager as often as through code.
- Keep INP attribution reporting running permanently, with an alert when a page group crosses the threshold.
- Require a quick performance check before adding any third-party script, including ones added through the tag manager.
- Review the client component boundaries in pull requests, especially new providers and layouts.
- Re-test key interactions on a mid-range phone after framework and dependency updates.
- Compare against other platforms when deciding where pages should live; our guide to Core Web Vitals for Framer, Webflow and Next.js shows where each tends to struggle.
Is fixing Next.js INP worth the effort?
Fixing Next.js INP is worth it when field data shows real pages failing, because slow responses frustrate visitors at the exact moment they try to act: opening the menu, switching a plan, submitting a form. It's not worth chasing lab scores on pages that already pass in the field.
INP is one of three Core Web Vitals, and a page experience signal rather than a dominant ranking factor. If you're new to the metrics, our explainer on Core Web Vitals for marketers and founders puts INP alongside loading and layout stability. For most marketing sites, the work is a short round of focused fixes, then a habit of not letting new scripts undo them.
