Back to Mantine

Usage with Next.js

apps/mantine.dev/src/pages/guides/next.mdx

9.1.15.9 KB
Original Source

import { Layout } from '@/layout'; import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.NextJs);

Usage with Next.js

<GetTemplates type="next" />

Generate new application

Follow the create-next-app guide to create a new Next.js application:

<NpmScript yarnScript="yarn create next-app --typescript" npmScript="npx create-next-app@latest --typescript" />

Installation

<PackagesInstallation />

PostCSS setup

Install PostCSS plugins and postcss-preset-mantine:

<InstallScript packages="postcss postcss-preset-mantine postcss-simple-vars" dev />

Create a postcss.config.cjs file at the root of your application with the following content:

js
module.exports = {
  plugins: {
    'postcss-preset-mantine': {},
    'postcss-simple-vars': {
      variables: {
        'mantine-breakpoint-xs': '36em',
        'mantine-breakpoint-sm': '48em',
        'mantine-breakpoint-md': '62em',
        'mantine-breakpoint-lg': '75em',
        'mantine-breakpoint-xl': '88em',
      },
    },
  },
};

Setup with pages router

Add styles imports and MantineProvider to the pages/_app.tsx file:

tsx
// Import styles of packages that you've installed.
// All packages except `@mantine/hooks` require styles imports
import '@mantine/core/styles.css';

import type { AppProps } from 'next/app';
import { createTheme, MantineProvider } from '@mantine/core';

const theme = createTheme({
  /** Put your mantine theme override here */
});

export default function App({ Component, pageProps }: AppProps) {
  return (
    <MantineProvider theme={theme}>
      <Component {...pageProps} />
    </MantineProvider>
  );
}

Create a pages/_document.tsx file with the ColorSchemeScript component. Note that it's required even if you use only one color scheme in your application.

tsx
import { Head, Html, Main, NextScript } from 'next/document';
import { ColorSchemeScript, mantineHtmlProps } from '@mantine/core';

export default function Document() {
  return (
    <Html lang="en" {...mantineHtmlProps}>
      <Head>
        <ColorSchemeScript defaultColorScheme="auto" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

All set! Start the development server:

bash
npm run dev

Setup with app router

Add MantineProvider, ColorSchemeScript and styles imports to the app/layout.tsx file:

tsx
// Import styles of packages that you've installed.
// All packages except `@mantine/hooks` require styles imports
import '@mantine/core/styles.css';

import { ColorSchemeScript, MantineProvider, mantineHtmlProps } from '@mantine/core';

export const metadata = {
  title: 'My Mantine app',
  description: 'I have followed setup instructions carefully',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en" {...mantineHtmlProps}>
      <head>
        <ColorSchemeScript />
      </head>
      <body>
        <MantineProvider>{children}</MantineProvider>
      </body>
    </html>
  );
}

All set! Start the development server:

bash
npm run dev

app + pages router together

If you use both app and pages router in one application, you need to setup both pages/_app.tsx and app/layout.tsx files as described above.

tsx
import Link from 'next/link';
import { Button } from '@mantine/core';

function Demo() {
  return (
    <Button component={Link} href="/hello">
      Next link button
    </Button>
  );
}

Server components

All Mantine components require context to support default props and Styles API. Mantine components cannot be used as server components. This means that components will render both on the server and client.

Entry points of all @mantine/* packages (index.js files) have the 'use client'; directive at the top of the file – you don't need to add 'use client'; to your pages/layouts/components.

Compound components in server components

Some components like Popover have associated compound components (Component.XXX), where XXX is a compound component name. Compound components cannot be used in server components. Instead, use the ComponentXXX syntax or add the 'use client'; directive to the top of the file.

Example that won't work in server components:

tsx
import { Popover } from '@mantine/core';

// This will throw an error
export default function Page() {
  return (
    <Popover>
      <Popover.Target>Target</Popover.Target>
      <Popover.Dropdown>Dropdown</Popover.Dropdown>
    </Popover>
  );
}

Example with 'use client'; directive:

tsx
'use client';

import { Popover } from '@mantine/core';

// No error
export default function Page() {
  return (
    <Popover>
      <Popover.Target>Target</Popover.Target>
      <Popover.Dropdown>Dropdown</Popover.Dropdown>
    </Popover>
  );
}

Example with ComponentXXX syntax:

tsx
import {
  Popover,
  PopoverDropdown,
  PopoverTarget,
} from '@mantine/core';

// No error
export default function Page() {
  return (
    <Popover>
      <PopoverTarget>Trigger</PopoverTarget>
      <PopoverDropdown>Dropdown</PopoverDropdown>
    </Popover>
  );
}

app router tree shaking

To enable tree shaking with app router, enable the experimental optimizePackageImports feature in your next.config.mjs:

tsx
export default {
  // ...other configuration
  experimental: {
    optimizePackageImports: ['@mantine/core', '@mantine/hooks'],
  },
};

Troubleshooting

If you have any issues with Mantine in your Next.js application, please check the Help Center article that covers the most common issues with app router and server components.