Featured image of post Next JS Snippets Collection

Next JS Snippets Collection

Collected Bits of Next JS Wisdom

Next.js: the framework that turns React into a supercharged, server-rendered, SEO-friendly powerhouse.

If React is a Swiss Army knife, Next.js is that version with a built-in flamethrower and bottle opener.

:)
(How’s that for a visual? )

A Brief History of Next.js (Or: How We Got Here)

Next.js was born in 2016, crafted by the fine folks at Vercel (then called ZEIT). Their mission? To make React even better by simplifying server-side rendering (SSR) and static site generation (SSG).

Before Next.js, doing SSR with React felt like assembling IKEA furniture without a manual—painful, confusing, and somehow always missing one key piece.

Here’s how Next.js evolved over the years:

VersionRelease DateNotable Features
1.02016-10-25Server-side rendering (SSR), simple routing
2.02017-03-27Static exports, custom server support
3.02017-08-14Prefetching, dynamic imports
4.02017-12-07Improved SSR, better error handling
5.02018-03-09Webpack 4, multi-zone support
6.02018-06-27Automatic static optimization
7.02018-11-21Faster builds, improved prefetching
8.02019-02-27Incremental Static Regeneration (ISR)
9.02019-07-17API routes, automatic static generation
10.02020-10-27Internationalized routing, image optimization
11.02021-06-15Webpack 5, faster refresh
12.02021-10-26Middleware, React 18 support
13.02022-10-25App directory, RSC (React Server Components)
14.02023-10-26TurboPack, huge performance boost

1. Creating a Simple Page in Next.js

Every file inside the /pages directory is a route automatically. Here’s the simplest page you can create:

1
2
3
4
// pages/index.js
export default function Home() {
  return <h1>Welcome to Next.js!</h1>;
}

2. Dynamic Routing with URL Parameters

Need dynamic routes? No problem.

1
2
3
4
5
6
7
8
// pages/post/[id].js
import { useRouter } from 'next/router';

export default function Post() {
  const router = useRouter();
  const { id } = router.query;
  return <h1>Post ID: {id}</h1>;
}

3. Server-Side Rendering (SSR)

Need to fetch data on each request? Use getServerSideProps.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// pages/ssr-example.js
export async function getServerSideProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await res.json();
  return { props: { post: data } };
}

export default function SSRPage({ post }) {
  return <h1>{post.title}</h1>;
}

4. Static Site Generation (SSG)

For super-fast performance, pre-render pages at build time.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// pages/ssg-example.js
export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await res.json();
  return { props: { post: data } };
}

export default function SSGPage({ post }) {
  return <h1>{post.title}</h1>;
}

5. API Routes (Your Built-in Backend)

Want to create an API inside your Next.js project? Here you go:

1
2
3
4
// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello, API!' });
}

6. Using Middleware for Custom Logic

Middleware can intercept requests before they hit your pages.

1
2
3
4
5
6
7
8
// middleware.js
import { NextResponse } from 'next/server';

export function middleware(req) {
  if (!req.cookies.authToken) {
    return NextResponse.redirect('/login');
  }
}

7. Optimized Images with Next.js

Next.js has an amazing <Image /> component that auto-optimizes images.

1
2
3
4
5
import Image from 'next/image';

export default function OptimizedImage() {
  return <Image src="/example.jpg" width={500} height={500} alt="Example" />;
}

8. Using Edge Functions (Next.js 12+)

Run server-side code closer to the user!

1
2
3
4
5
6
// pages/api/edge-example.js
export default async function handler(req) {
  return new Response('Hello from the edge!', {
    status: 200,
  });
}

9. Incremental Static Regeneration (ISR)

Regenerate static pages dynamically without a full rebuild.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// pages/isr-example.js
export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await res.json();
  return { props: { post: data }, revalidate: 10 };
}

export default function ISRPage({ post }) {
  return <h1>{post.title}</h1>;
}

10. Internationalized Routing (i18n)

Easily handle multiple languages without a headache.

1
2
3
4
5
6
7
// next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'es', 'fr'],
    defaultLocale: 'en',
  },
};

11. Custom _app.js for Global State Management

Want to persist global state across pages? Modify _app.js.

1
2
3
4
5
6
7
8
9
// pages/_app.js
import { useState } from 'react';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  const [user, setUser] = useState(null);
  return <Component {...pageProps} user={user} setUser={setUser} />;
}
export default MyApp;

12. Custom _document.js for Modifying <html> and <body>

Use _document.js to modify the document structure.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <link rel="stylesheet" href="/custom.css" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

13. Fetch Data on the Client Side with useEffect

If you don’t need SSR, fetch data client-side instead.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { useEffect, useState } from 'react';

export default function ClientFetch() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/example')
      .then((res) => res.json())
      .then((data) => setData(data));
  }, []);

  return <div>{data ? JSON.stringify(data) : 'Loading...'}</div>;
}

14. Creating Protected Routes (Authentication)

Protect pages by checking authentication status.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// pages/protected.js
import { useRouter } from 'next/router';
import { useEffect } from 'react';

export default function ProtectedPage() {
  const router = useRouter();

  useEffect(() => {
    const token = localStorage.getItem('authToken');
    if (!token) router.push('/login');
  }, []);

  return <h1>Protected Content</h1>;
}

15. Custom Express Server with Next.js

Want more control? Use a custom server.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// server.js
const express = require('express');
const next = require('next');
const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  server.get('*', (req, res) => {
    return handle(req, res);
  });

  server.listen(3000, () => console.log('Server running on port 3000'));
});

16. Adding SEO Meta Tags Dynamically

Boost SEO with dynamic <meta> tags.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import Head from 'next/head';

export default function SEOPage() {
  return (
    <>
      <Head>
        <title>SEO in Next.js</title>
        <meta name="description" content="Learn SEO in Next.js" />
      </Head>
      <h1>SEO Page</h1>
    </>
  );
}

17. Styling with Tailwind CSS

Next.js works great with Tailwind.

1
2
3
4
5
6
7
// Install Tailwind: npm install tailwindcss postcss autoprefixer
// Add Tailwind to globals.css
import 'tailwindcss/tailwind.css';

export default function TailwindExample() {
  return <h1 className="text-4xl font-bold text-blue-500">Hello Tailwind!</h1>;
}

18. Using next/script for Third-Party Scripts

Load third-party scripts efficiently.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import Script from 'next/script';

export default function ExternalScript() {
  return (
    <>
      <h1>Using Next.js Script</h1>
      <Script src="https://example.com/script.js" strategy="lazyOnload" />
    </>
  );
}

Improve navigation speed with prefetching.

1
2
3
4
5
6
7
8
9
import Link from 'next/link';

export default function PrefetchExample() {
  return (
    <Link href="/about" prefetch>
      Go to About Page
    </Link>
  );
}

20. Handling 404 Pages

Customize your 404 error page.

1
2
3
4
// pages/404.js
export default function Custom404() {
  return <h1>Oops! Page Not Found 😢</h1>;
}

21. Using Middleware for Custom Headers

Want to add security headers or modify responses dynamically? Middleware is your best friend.

1
2
3
4
5
6
7
8
// middleware.js
import { NextResponse } from 'next/server';

export function middleware(req) {
  const res = NextResponse.next();
  res.headers.set('X-Custom-Header', 'MyHeaderValue');
  return res;
}

22. Prefetching API Requests with SWR

For blazing-fast UI updates, use SWR for API fetching with caching and revalidation.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import useSWR from 'swr';

const fetcher = (url) => fetch(url).then((res) => res.json());

export default function Dashboard() {
  const { data, error } = useSWR('/api/data', fetcher);

  if (error) return <div>Failed to load</div>;
  if (!data) return <div>Loading...</div>;

  return <h1>Welcome, {data.user}</h1>;
}

23. Generating Dynamic Sitemaps

Make sure search engines love your Next.js app with a dynamic sitemap.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// pages/sitemap.xml.js
import { getServerSideProps } from 'next';

export default function Sitemap() {}

export async function getServerSideProps({ res }) {
  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <url><loc>https://example.com/</loc></url>
    </urlset>`;
  res.setHeader('Content-Type', 'text/xml');
  res.write(sitemap);
  res.end();
  return { props: {} };
}

24. Optimizing Fonts with next/font

Improve performance by loading Google Fonts the Next.js way.

1
2
3
4
5
6
7
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function Home() {
  return <h1 className={inter.className}>Optimized Fonts!</h1>;
}

25. Caching API Responses with revalidate

Want data that refreshes every 10 seconds? Incremental Static Regeneration (ISR) has you covered.

1
2
3
4
5
6
7
8
9
export async function getStaticProps() {
  const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
  const data = await res.json();

  return {
    props: { post: data },
    revalidate: 10,
  };
}

26. Creating a Custom 500 Error Page

Make sure your error pages are just as polished as the rest of your app.

1
2
3
4
// pages/500.js
export default function Custom500() {
  return <h1>Something went wrong! 🚨</h1>;
}

27. Enabling React Strict Mode

For better debugging and catching potential issues, enable strict mode in next.config.js.

1
2
3
4
// next.config.js
module.exports = {
  reactStrictMode: true,
};

28. Lazy Loading Components for Performance Boosts

Reduce initial load times by dynamically importing components.

1
2
3
4
5
6
7
8
9
import dynamic from 'next/dynamic';

const HeavyComponent = dynamic(() => import('../components/HeavyComponent'), {
  ssr: false,
});

export default function Page() {
  return <HeavyComponent />;
}

29. Using WebSockets in Next.js API Routes

Need real-time updates? WebSockets work inside API routes!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// pages/api/socket.js
import { Server } from 'socket.io';

export default function handler(req, res) {
  if (!res.socket.server.io) {
    const io = new Server(res.socket.server);
    res.socket.server.io = io;
  }
  res.end();
}

30. Customizing the Build Output Directory

Change the default .next folder to something custom in next.config.js.

1
2
3
4
// next.config.js
module.exports = {
  distDir: 'build',
};

31. Advanced Dynamic Routing with Catch-All Routes

Need a route that captures multiple segments? Catch-all routes got you covered.

1
2
3
4
5
6
7
8
9
// pages/blog/[...slug].js
import { useRouter } from 'next/router';

export default function BlogPost() {
  const router = useRouter();
  const { slug } = router.query;

  return <h1>Blog Post: {slug?.join(' / ')}</h1>;
}

32. Using Edge Functions for Lightning-Fast Requests

Deploy serverless functions at the edge for near-instant responses.

1
2
3
4
5
6
7
8
// pages/api/edge.js
export const config = { runtime: 'edge' };

export default async function handler(req) {
  return new Response(JSON.stringify({ message: 'Hello from the edge!' }), {
    headers: { 'Content-Type': 'application/json' },
  });
}

33. Optimizing API Responses with Cache-Control

Use cache headers to boost performance and reduce unnecessary requests.

1
2
3
4
5
// pages/api/cached-data.js
export default function handler(req, res) {
  res.setHeader('Cache-Control', 's-maxage=60, stale-while-revalidate');
  res.json({ message: 'Cached response' });
}

34. Implementing Role-Based Access Control (RBAC)

Secure pages based on user roles dynamically.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// components/ProtectedRoute.js
import { useRouter } from 'next/router';
import { useEffect } from 'react';

export default function ProtectedRoute({ user, allowedRoles, children }) {
  const router = useRouter();
  useEffect(() => {
    if (!user || !allowedRoles.includes(user.role)) {
      router.push('/unauthorized');
    }
  }, [user, allowedRoles, router]);

  return <>{children}</>;
}

35. Custom Webpack Configuration

Extend Next.js with a custom Webpack config.

1
2
3
4
5
6
7
8
9
// next.config.js
module.exports = {
  webpack: (config) => {
    config.module.rules.push({
      test: /\.md$/, use: 'raw-loader',
    });
    return config;
  },
};

36. Prefetching API Data for Better UX

Preload API calls before users even navigate to a page.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// pages/index.js
import Link from 'next/link';
import { useEffect } from 'react';

export default function Home() {
  useEffect(() => {
    fetch('/api/data'); // Prefetch API data
  }, []);

  return <Link href="/dashboard">Go to Dashboard</Link>;
}

37. Custom ESLint Rules in Next.js

Force best practices with custom ESLint rules.

1
2
3
4
5
6
7
// .eslintrc.js
module.exports = {
  rules: {
    'no-console': 'warn',
    'react/no-unescaped-entities': 'off',
  },
};

38. Testing Next.js Apps with Jest and React Testing Library

Unit test your Next.js components like a pro.

1
2
3
4
5
6
7
8
// __tests__/index.test.js
import { render, screen } from '@testing-library/react';
import Home from '../pages/index';

test('renders welcome message', () => {
  render(<Home />);
  expect(screen.getByText(/Welcome to Next.js!/i)).toBeInTheDocument();
});

39. Implementing Webhooks for Real-Time Events

Trigger actions based on external events.

1
2
3
4
5
6
7
8
9
// pages/api/webhook.js
export default async function handler(req, res) {
  if (req.method === 'POST') {
    console.log('Webhook received:', req.body);
    res.status(200).send('OK');
  } else {
    res.status(405).send('Method Not Allowed');
  }
}

40. Handling Background Jobs with Serverless Functions

Process long-running tasks asynchronously.

1
2
3
4
5
// pages/api/background-task.js
export default async function handler(req, res) {
  setTimeout(() => console.log('Background job done!'), 5000);
  res.status(200).json({ status: 'Job started' });
}