Creating Varied Layouts for Different NextJS Pages
Tags: nextjs, layoutvariations, pagecomponents, userexperience
Published: 2023-09-19 09:44:43

✨ [**Watch on YouTube**](https://youtu.be/hrSBxLlZsCc)  |  🐙 [GitHub](https://github.com/radzionc/reactkit)  |  🎮 [Demo](https://reactkit.radzion.com)

In this post, we will learn how to create different layouts for different NextJS pages. We'll examine how this is done at [increaser.org](https://increaser.org), which incorporates four layout variations. Although Increaser's repository is private, you can find all the code in the [ReactKit repository](https://github.com/radzionc/reactkit) as it also uses different layouts for the landing page and the remaining pages.

## Why not use layout components directly in the page component?

We could use different layout components directly in the page component. However, the issue arises when we navigate between pages with the same layout. The layout ends up being re-rendered. This becomes problematic when you have a sidebar layout with a scroll, and, as you scroll down and move to another page, the scroll resets. Thus, we need a method that allows different layouts for different pages, while also maintaining the layout when we navigate between pages with the same layout for improved user experience.

![Sidebar](https://cdn-images-1.medium.com/proxy/1*zjH-jVRxgx_tM0s8UuAT0w.jpeg)

## How to create different layouts for different pages?

At [Increaser](https://increaser.org), we implement four different layouts:

- Authorization pages that have the same top bar as the landing page.
- App pages with the sidebar.
- Project pages that also contain additional navigation between projects.
- A full-screen focus page that lacks any navigation.

To accomplish this, we use three helper functions: `makeAppPage`, `makeAuthPage`, and `makeProjectsPage`.

```tsx
import { Page, GetLayout } from "layout/Page"
import { AppPageLayout } from "focus/components/AppPageLayout"

const getAppPageLayout: GetLayout = (page) => (
  <AppPageLayout>{page}</AppPageLayout>
)

export const makeAppPage = (page: Page) => {
  page.getLayout = getAppPageLayout

  return page
}
```

All of these functions look alike. Each is a function that takes a component and adds a `getLayout` function to it, which wraps the page within a specific layout.

```tsx
import { NextPage } from "next"
import { ReactNode } from "react"

export type GetLayout = (page: ReactNode) => ReactNode

export type Page<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: GetLayout
}
```

The `Page` type is simply a NextJS page with an extra function. The `GetLayout` type describes a function that takes one React node and returns another React node.

## How to use page layout helpers?

Here is how we use our helpers: we wrap the page component with the helper function, as exemplified in this sign-up page.

```tsx
import { SignUpContent } from "auth/components/SignUpContent"
import { makeAuthPage } from "layout/makeAuthPage"

export default makeAuthPage(SignUpContent)
```

Without the helper, we would have more code to write:

```tsx
import { SignUpContent } from "auth/components/SignUpContent"
import { AppPageLayout } from "focus/components/AppPageLayout"
import { Page } from "layout/Page"

const SignUpPage: Page = SignUpContent

export default SignUpPage

SignUpPage.getLayout = (page) => <AppPageLayout>{page}</AppPageLayout>
```

## \_app.tsx and getLayout

In which context do we call the `getLayout` function?

```tsx
function MyApp({ Component, pageProps }: MyAppProps) {
  const getLayout = Component.getLayout || ((page: ReactNode) => page)
  const component = getLayout(<Component {...pageProps} />)

  return (
    <ThemeProvider>
      <GlobalStyle fontFamily={inter.style.fontFamily} />
      {component}
    </ThemeProvider>
  )
}

export default MyApp
```

It will be the `_app.tsx` file that calls the `getLayout` function. If the page lacks a `getLayout` function like the focus page at [Increaser](https://increaser.org), it will simply return the page component.