With ever so increasing rise in popularity of Next.js, it has become quite a standard to use it for server-side React web applications. So that means the Next.js cheat sheet will be your main asset going forward.
It gets all the features of React.js – the JavaScript’s UI library to build components and adds so many additional features that sometimes as a Next.js developer it’s hard to catch up on the different code snippets, commands to run, packages to install, and more.
To solve this issue, we have created a to-the-point Next.js cheat sheet of all the features that will benefit all developers – be they a beginner or a pro. Let’s dive in!
What is Next.js?
According to its definition on the official docs:
- Next.js is a flexible React framework that gives you building blocks to create fast web applications.

Basically, it provides some of the crucial features and building blocks on top of a standard React.js application to make a modern website and apps.
Here are some of those important features (amongst others) that we will discuss:
- Setup
- Create pages
- Fetch data
- Style your Next.js app
- Optimize images and fonts
- Linting your code
- TypeScript support
- Using scripts
- App-level routing
- API routing
- Middlewares
- Authentication
- Testing
Explore our collection of Nextjs templates to accelerate your web development projects. These pre-designed frameworks provide a solid foundation for building modern and scalable web applications.
Next.js Cheat Sheet

Given below is the next.js cheat sheet that you can use in your next project.
1. Setup
In this first step of the next.js cheat sheet, we will create a Next.js app, the recommended process is to use the official create-next-app command which sets up all the necessary files, folders, and configuration automatically.
npx create-next-app@latest
# OR
yarn create next-app
Then run npm run dev or yarn dev to start the local development server on http://localhost:3000.
Alternatively, if you manually want to install Next.js, then first you should install next, react, and react-dom in your project as:
npm install next react react-dom
# OR
yarn add next react react-dom
Inside your package.json file, add the following scripts:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
2. Create pages
To create a simple static page, under the pages directory, create a file named demo.js which exports a React component:
function Demo() {
return <h1>Demo</h1>
}
export default Demo
This page will be available at http://localhost:3000/demo of your local environment.
3. Fetch data
In the next.js cheat sheet, there are many ways to fetch data from external sources to your Next.js app, here are some:
- getServerSideProps: if you want your app to pre-render a page on each request, then the getServerSideProps function should be exported as so:
export async function getServerSideProps(context) {
return {
props: {},
}
}
Here’s an example to fetch data at request time which pre-renders the result it gets back from the data source:
function Page({ data }) {
// Code to render the `data`
}
export async function getServerSideProps() {
const res = await fetch(`https://.../data`)
const data = await res.json()
return { props: { data } }
}
export default Page
- getStaticPaths: if you want to dynamically generate routes on your app alongside with getStaticProps then, getStaticPaths will pre-render all the paths provided to it as:
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } }
],
fallback: true
};
}
- getStaticProps: if you want Next.js to generate a page at build time using the props passed to it, then getStaticProps should be exported as:
export async function getStaticProps(context) {
return {
props: {},
}
}
Note that the props here must be passed to the page component as props. An example of its usage when you want the data to fetch from a CMS is as follows:
function BlogPosts ({ posts }) {
return (
<>
{posts.map((post) => (
<h1>{post.title}</h1>
<p>{post.summary}</p>
))}
</>
)
}
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()
return {
props: {
posts,
},
}
}
export default BlogPosts
- Incremental Static Regeneration(ISR): if you want to create or update existing static pages after you’ve built your site, then ISR allows you to statically generate on a per-page basis. This means that now you don’t need to rebuild the entire site from scratch.
For this to work, you just need to add the revalidate prop to the getStaticProps method:
export async function getStaticProps(context) {
return {
props: {},
revalidate: 5 // this means the request to re-generate the page will berevalidated once in every 5 seconds
}
}
- Fetch data on client-side: this can be done in two different ways — either via the useEffect hook as:
function User() {
const [data, setData] = useState(null)
const [isLoading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetch('api/user-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (isLoading) return <p>Loading user data...</p>
if (!data) return <p>No user data found</p>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
or via the SWR library which handles caching, revalidation, focus tracking, re-fetching on intervals, and more as:
import useSWR from 'swr'
const fetcher = (...args) => fetch(...args).then((res) => res.json())
function User() {
const { data, error } = useSWR('/api/user-data', fetcher)
if (error) return <div>Failed to load user data</div>
if (!data) return <div>Loading user data...</div>
return (
<div>
<h1>{data.name}</h1>
<p>{data.bio}</p>
</div>
)
}
4. Style your Next.js app
There are many ways to style your apps in this step of the next.js cheat sheet, some of the common methods are:
- Global styling: import the global styles.css in your pages/_app.js where these styles will apply to all pages and components in your app as:
import '../styles.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
- Component-Level CSS: Next.js supports CSS Modules where you can name the files as [name].module.css and then import it on a specific component. Here’s an example:
// Button.module.css
.error {
color: white;
background-color: red;
}
// Button.jsx
import styles from './Button.module.css'
export function Button() {
return (
<button
type="button"
className={styles.error}
>
Cancel
</button>
)
}
- Using SASS: first, you need to install the SASS package on your Next.js app:
npm install --save-dev sass
Then you can configure the SASS compiler options in next.config.js file:
const path = require('path')
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
},
}
Also Read: Angular vs React vs Vue
5. Optimize images and fonts
In this step of the next.js cheat sheet, to optimize images you should use the built-in Image component. Install it in your project as:
import Image from 'next/image'
Then give it an src attribute as shown in the following example:
import Image from 'next/image'
const myLoader = ({ src, width, quality }) => {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}
const MyImage = (props) => {
return (
<Image
loader={myLoader}
src="me.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}
Next.js automatically optimizes the fonts used by automatically inline font CSS at build time. But to use a web font, you can add it to the Custom Document file as:
// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<link
href="https://fonts.googleapis.com/css2?family=Inter&display=optional"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
6. Linting your code
You can use ESLint out-of-the-box for linting. Simply add the following script to the package.json file:
"scripts": {
"lint": "next lint"
}
Now you can run npm run lint or yarn lint to start the linter. If you are using ESLint in a monorepo where Next.js isn’t installed in your root directory, you just simply add the rootDir to your .eslintrc file:
{
"extends": "next",
"settings": {
"next": {
"rootDir": "packages/my-app/"
}
}
}
To use Prettier with ESLint settings, first install the dependency:
npm install --save-dev eslint-config-prettier
# OR
yarn add --dev eslint-config-prettier
And then add prettier to your existing ESLint configuration file:
{
"extends": ["next", "prettier"]
}
7. TypeScript support
TypeScript support is also one of the next.js cheat sheets. To use TypeScript with Next.js when you start an app, use the create-next-app command along with the –ts or –typescript flag:
npx create-next-app@latest --ts
# or
yarn create next-app --typescript
This will spin up a new Next.js project with all the Typescript files and components without any extra configuration.
But if you want to integrate TypeScript in an existing project then, create a new tsconfig.json file at the root of the project directory. Then run npm run dev or yarn dev, with this Next.js will guide you through the installation of the required packages to finish setting up TypeScript integration.
8. Using scripts
We are going to use scripts in this step of the next.js cheat sheet, the native HTML <script> element is replaced by next/script component in Next.js. Here’s an example of loading a Google Analytics script:
import Script from 'next/script'
export default function Home() {
return (
<>
<Script src="https://www.google-analytics.com/analytics.js" />
</>
)
}
First, you import the script component:
import Script from 'next/script'
Next, there are different ways to handle scripts with this component which can be set by the strategy property with one of the following three values:
- beforeInteractive: load the script before the page is interactive.
- afterInteractive: load the script immediately after the page becomes interactive.
- lazyOnload: load the script during idle time.
Here’s an example:
<script
src="https://cdn.jsdelivr.net/npm/cookieconsent@3/build/cookieconsent.min.js"
strategy="beforeInteractive"
/>
9. App-level routing
In the next step of the next.js cheat sheet, Next.js has a file-system-based router that works on the concept of pages. You can either have index routes like pages/index.js which map to / and pages/blog/index.js which map to /blog.
Or you can have nested routes where it supports nested files. For example, a file located on pages/blog/my-post.js will route to /blog/my-post.
For dynamic routes, you need to use the bracket syntax so that it can match named parameters. For example, pages/[username]/settings.js will map to /johndoe/settings.
The <Link> component is used to do client-side route transitions. First, you need to import it as:
import Link from 'next/link'
Then, use it in a component:
import Link from 'next/link'
function Home() {
return (
<ul>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li>
<Link href="/about">
<a>About Us</a>
</Link>
</li>
<li>
<Link href="/blog/hello-world">
<a>Blog Post</a>
</Link>
</li>
</ul>
)
}
export default Home
For dynamic paths, you can use string interpolation to create the desired path:
import Link from 'next/link'
function Posts({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${encodeURIComponent(post.slug)}`}>
<a>{post.title}</a>
</Link>
</li>
))}
</ul>
)
}
export default Posts
10. API routing
Any file inside the pages/api folder is mapped to /api/* which will be treated as an API endpoint. For example, to return a JSON response with an OK status code of 200, you can export a handler function with req and res passed as parameters:
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
To handle different HTTP methods, you can use the req.method in your request handler:
export default function handler(req, res) {
if (req.method === 'POST') {
// Process a POST request
} else {
// Handle any other HTTP method
}
}
11. Middlewares
- To use middlewares in Next.js, first install the latest version of Next:
npm install next@latest
- Then create a _middleware.ts file inside your /pages directory
- Finally, export a middleware function form the same file:
import type { NextFetchEvent, NextRequest } from 'next/server'
export function middleware(req: NextRequest, ev: NextFetchEvent) {
return new Response('Hello, world!')
}
For example, here is an example where middleware is used for logging:
import { NextRequest } from 'next/server'
// Regex for public files
const PUBLIC_FILE = /\.(.*)$/
export default function middleware(req: NextRequest) {
// Only log for visited pages
if (!PUBLIC_FILE.test(req.nextUrl.pathname)) {
// We fire and forget this request to avoid blocking the request until completion
// and let logging occur in the background
fetch('https://in.logtail.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.LOGTAIL_TOKEN}`,
},
body: JSON.stringify({
message: 'Log from the edge',
nested: {
page: req.nextUrl.href,
referrer: req.referrer,
ua: req.ua?.ua,
geo: req.geo,
},
}),
})
}
}
Also Read: React Table: A detailed guide with Examples
12. Authentication
There are many different ways to authenticate a user in a Next.js app. Some of the common ones are:
- Authenticating statically generated pages: here, your page can render a loading state from the server after which it will fetch the user data from the client side. In the following example, the page renders a loading skeleton state and once the request is met, it shows the user’s name:
import useUser from '../lib/useUser'
import Layout from '../components/Layout'
const Profile = () => {
// Fetch the user client-side
const { user } = useUser({ redirectTo: '/login' })
// Server-render loading state
if (!user || user.isLoggedIn === false) {
return <Layout>Loading...</Layout>
}
// Once the user request finishes, show the user
return (
<Layout>
<h1>Your Profile</h1>
<pre>{JSON.stringify(user, null, 2)}</pre>
</Layout>
)
}
export default Profile
- Authenticating server-rendered pages: here you need to export an async getServerSideProps() function from a page by which Next.js will pre-render this page on each request. Here’s an example where if there is a session, then the user is returned as a prop to the Profile component:
import withSession from '../lib/session'
import Layout from '../components/Layout'
export const getServerSideProps = withSession(async function ({ req, res }) {
const { user } = req.session
if (!user) {
return {
redirect: {
destination: '/login',
permanent: false,
},
}
}
return {
props: { user },
}
})
const Profile = ({ user }) => {
// Show the user. No loading state is required
return (
<Layout>
<h1>Your Profile</h1>
<pre>{JSON.stringify(user, null, 2)}</pre>
</Layout>
)
}
export default Profile
- Authenticating with third-party providers: for common authentication providers like Auth0, Firebase, Supabase, etc, you can take a look at the official GitHub repository for examples of how to set up and configure your own Next.js app.
13. Testing
The last step of the next.js cheat sheet, Just like with authentication, testing can be done in a lot of different ways and with different testing tools. Here’s how to setup testing with common tools:
- Testing with Cypress: start off with the with-cypress example to quickly start a Next.js app with Cypress as:
npx create-next-app@latest --example with-cypress with-cypress-app
Or manually, install the cypress package:
npm install --save-dev cypress
Then add it to the scripts field of your package.json file:
"scripts": {
...
"cypress": "cypress open",
}
Finally, run Cypress with the following command:
npm run cypress
To create a Cypress test file. Simply create a file under cypress/integration/app.spec.js as:
describe('Navigation', () => {
it('should navigate to the about page', () => {
// Start from the index page
cy.visit('http://localhost:3000/')
// Find a link with an href attribute containing "about" and click it
cy.get('a[href*="about"]').click()
// The new url should include "/about"
cy.url().should('include', '/about')
// The new page should contain an h1 with "About page"
cy.get('h1').contains('About Page')
})
})
- Testing with Jest and React Testing Library: again you can use it quickly with the community provided with-jest example while you spin off a new Next project:
npx create-next-app@latest --example with-jest with-jest-app
Or manually, you can install Jest, React Testing Library, and Jest DOM packages:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Then create a jest.config.js file in the project’s root directory:
const nextJest = require('next/jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
// Add a test script to the package.json file:
"scripts": {
...
"test": "jest --watch"
}
// Then create a Jest test file under __tests__/index.test.jsx as:
import { render, screen } from '@testing-library/react'
import Home from '../pages/index'
describe('Home', () => {
it('renders a heading', () => {
render(<Home />)
const heading = screen.getByRole('heading', {
name: /welcome to next\.js!/i,
})
expect(heading).toBeInTheDocument()
})
})
To run the test simply execute the npm run test command.
In this article, you got to know what is Next.js in brief, the Next.js Cheat Sheet is, and how it helps in making modern React-based websites and apps. Then you saw how to set up a Next.js project, how to fetch data, optimize assets, add TypeScript support, use linters, integrate testing tools, and more!