Skip to main content
Back to Blog
Next.jsSuspenseUX

Next.js Loading UI and Suspense: Streaming and Skeleton Screens

6 min read

How to implement loading states and streaming in Next.js using the loading.tsx convention, React Suspense boundaries, and skeleton screens for a smooth user experience.

Loading states and streaming are fundamental to the user experience of modern web applications, and Next.js 15 provides first-class support for both through the loading.tsx file convention and React Suspense boundaries. Muhammad Sufyan of Sufyan Frontend explains how to implement smooth, professional loading experiences in your Next.js projects.

The loading.tsx Convention

The simplest way to add loading states in Next.js App Router is the loading.tsx file. Place a loading.tsx file alongside any page.tsx and Next.js will automatically show it while the page is loading, using React Suspense under the hood. The user sees a skeleton or spinner immediately on navigation, rather than staring at a blank screen.

// app/blog/loading.tsx
export default function Loading() {
  return (
    <div className="max-w-3xl mx-auto px-4 pt-24">
      {[...Array(3)].map((_, i) => (
        <div key={i} className="bg-card rounded-2xl p-6 mb-6 animate-pulse">
          <div className="h-4 bg-white/10 rounded w-1/3 mb-4" />
          <div className="h-6 bg-white/10 rounded w-3/4 mb-3" />
          <div className="h-4 bg-white/10 rounded w-full" />
        </div>
      ))}
    </div>
  );
}

React Suspense for Granular Loading States

For more granular control, wrap individual data-fetching components in Suspense boundaries with custom fallback UIs. This enables streaming — the server sends the page shell immediately and streams in each Suspense boundary as its data resolves, creating a progressive loading experience that feels significantly faster than waiting for all data to load before rendering anything.

Skeleton Screens Best Practices

  • Match skeleton dimensions closely to actual content to prevent layout shift on load
  • Use animate-pulse from Tailwind for a gentle shimmer effect
  • Avoid spinners for content areas — skeletons communicate structure better
  • Keep skeletons simple — they should indicate layout, not replicate every detail

Conclusion

Thoughtful loading states are the difference between an app that feels fast and one that feels slow, regardless of actual data fetch times. Muhammad Sufyan implements loading.tsx and skeleton screens across his production Next.js projects to ensure users always see immediate feedback. Visit https://sufyan-frontend.vercel.app to see Sufyan Frontend Developer's approach to smooth page transitions in action.