Emergency WordPress Hack Cleanup?
sales@inceptusdigital.com |
← Back to Insights

Fixing High INP & LCP in Next.js 15 App Router: A Step-by-Step Core Web Vitals Optimization Guide (2026)

Development
Fixing High INP & LCP in Next.js 15 App Router: A Step-by-Step Core Web Vitals Optimization Guide (2026)

Core Web Vitals are a major Google organic ranking factor. With Google replacing FID with Interaction to Next Paint (INP), web applications that suffer from main-thread JavaScript bottlenecks during user clicks, taps, or keyboard events get penalized. In this guide, we break down step-by-step how to optimize Next.js 15 App Router applications for sub-15ms INP and sub-1.2s LCP scores.

📊 2026 Core Web Vitals Targets

INP Target
< 150ms (Good)
Target < 50ms for elite UX
LCP Target
< 2.5s (Good)
Target < 1.0s on 4G
CLS Target
< 0.1 (Good)
Target 0.00 zero shift

01. Understanding INP & LCP Bottlenecks in Next.js 15

In Next.js 15 App Router applications, poor INP is almost always caused by large client-side React component trees re-rendering synchronously during click events, heavy third-party tracking scripts, or dynamic layout recalculations. Poor LCP occurs when main hero images or web fonts lack proper fetch priority or are blocked behind dynamic server data fetches.

02. Step 1: Profiling Long Tasks with Long Animation Frames (LoAf) API

Instead of guessing which click handler is slow, instrument your Next.js client layout with the native Chrome Long Animation Frames (LoAf) API to record exact main-thread long tasks:

// Place in a client component or layout component
'use client'; import { useEffect } from 'react'; export default function PerformanceProfiler() { useEffect(() => { if (!('PerformanceObserver' in window)) return; const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.duration > 50) { console.warn(`[LoAf Long Task] Duration: ${entry.duration}ms`, entry); } } }); observer.observe({ type: 'long-animation-frame', buffered: true }); return () => observer.disconnect(); }, []); return null; }

03. Step 2: Eliminating React Hydration Bottlenecks

Ensure interactive elements use dynamic lazy imports and server component boundaries so that heavy client JavaScript is excluded from initial hydration.

// Bad: Importing heavy client modal directly into root layout
import HeavyAnalyticsModal from './HeavyAnalyticsModal';
// Good: Lazy load non-critical client component with SSR disabled
import dynamic from 'next/dynamic'; const HeavyAnalyticsModal = dynamic( () => import('./HeavyAnalyticsModal'), { ssr: false, loading: () => <div class="animate-pulse h-12 bg-slate-100 rounded-xl" /> } );

04. Step 3: Yielding Main Thread via scheduler.yield()

When filtering large datasets client-side, break up execution blocks using `scheduler.yield()` or `requestIdleCallback()` to allow the browser layout engine to process user input immediately:

async function handleFilterChange(query) { if ('scheduler' in window && 'yield' in window.scheduler) { await window.scheduler.yield(); } // Process filtered list without blocking click interaction frame setFilteredItems(performHeavyFilter(query)); }

05. Step 4: Sub-500ms LCP Asset Prioritization

For hero images or prominent product visuals, pass `priority` and explicit `sizes` props to `next/image` so Next.js generates preloading headers and high-priority fetch tags:

import Image from 'next/image'; export default function HeroBanner() { return ( <Image src="/images/hero-dashboard.webp" alt="SaaS Application Interface" width={1200} height={630} priority={true} fetchPriority="high" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px" className="w-full h-auto rounded-2xl shadow-2xl" /> ); }

06. Step 5: Zero-CLS Layout & next/font Optimization

Prevent Cumulative Layout Shift (CLS) during web font loading by utilizing `next/font/google` with automatic fallback metric overrides:

import { Plus_Jakarta_Sans } from 'next/font/google'; const jakarta = Plus_Jakarta_Sans({ subsets: ['latin'], display: 'swap', variable: '--font-jakarta', adjustFontFallback: true, // Zero CLS font metric adjustment });

07. Step 6: Edge Headers & next.config.js Optimization

Configure `next.config.js` to enable AVIF image format, HTTP/3 asset optimization, and granular caching headers:

// next.config.js
module.exports = { images: { formats: ['image/avif', 'image/webp'], minimumCacheTTL: 31536000, }, experimental: { optimizePackageImports: ['lucide-react', 'lodash-es'], }, };

Want a 95+ Core Web Vitals Next.js Web App or SaaS Platform?

Inceptus Digital builds high-performance web applications, custom SaaS platforms, and enterprise software designed for sub-second page loads and maximum conversion rates.

Explore Next.js Engineering Services →
Share this article

Need Custom Engineering or Growth Systems?

Our team helps ambitious brands build bespoke software, AI integrations, and high-conversion platforms.

Chat on WhatsApp