Mantine UI in Next.js 13 App Directory

Mantine UI in Next.js 13 app directory

❗ Next.js app directory architecture is still in beta and not recommended for production applications. The solution below is a temporary solution for Mantine in Next.js 13.

Mantine UI Components can only be used in Next.js 13 Client Components. By default, components in the app directory are Server Components. So the new use client directive must be used in any component that you want to use Mantine in. Find more on Client Components here: Client Components and use client in Next.js App Directory.

I did not develop this solution myself and will reference where the code originated.

Versions Tested With:

1"dependencies": {
2    "@emotion/react": "^11.10.5",
3    "@emotion/server": "^11.10.0",
4    "@mantine/core": "^5.10.2",
5    "@mantine/hooks": "^5.10.2",
6    "@mantine/next": "^5.10.2",
7    "next": "13.1.5",
8    "react": "18.2.0",
9  }

1. Create a new Next.js application

1npx create-next-app

Using create-next-app, go through multiple questions one of them doing you want to use the new experimental app directory architecture? Make sure to select that you do want to use the app directory. Note: I am also providing this example with TypeScript.

2. Install Mantine and Emotion packages

1// Choose your favorite package manager to install Mantine and emotion packages
2npm install @mantine/core @mantine/hooks @mantine/next @emotion/server @emotion/react
4yarn add @mantine/core @mantine/hooks @mantine/next @emotion/server @emotion/react
6pnpm install @mantine/core @mantine/hooks @mantine/next @emotion/server @emotion/react

Need more than the packages listed above? Find the complete list of installable packages in the Mantine usage with Next.js Guide.

3. Create an emotion.tsx file at the root of your app directory

The following code goes into an emotion.tsx file.

1// app/emotion.tsx
2"use client"
3import { CacheProvider } from "@emotion/react";
4import { useEmotionCache, MantineProvider } from "@mantine/core";
5import { useServerInsertedHTML } from "next/navigation";
7export default function RootStyleRegistry({
8  children
9}: {
10  children: React.ReactNode
11}) {
12  const cache = useEmotionCache();
13  cache.compat = true;
15  useServerInsertedHTML(() => (
16    <style
17      data-emotion={
18        `${cache.key} ${Object.keys(cache.inserted).join(" ")}`
19      }
20      dangerouslySetInnerHTML={{
21        __html: Object.values(cache.inserted).join(" "),
22      }}
23    />
24  ));
26  return (
27    <CacheProvider value={cache}>
28      <MantineProvider withGlobalStyles withNormalizeCSS>
29        {children}
30      </MantineProvider>
31    </CacheProvider>
32  )

The above code comes from Vitaly Rtishchev from this sample GitHub repository. The solution was found via: Mantine GitHub issue 2815.

4. Update layout.tsx with RootStyleRegistry

The RootStyleRegistry you just created needs to be added to the layout.tsx in the root of the app folder.

1// app/layout.tsx
2import RootStyleRegistry from './emotion'
3import './globals.css'
5export default function RootLayout({
6  children,
7}: {
8  children: React.ReactNode
9}) {
10  return (
11    <html lang="en-US">
12    <head />
13    <body>
14      <RootStyleRegistry>{children}</RootStyleRegistry>
15    </body>
16  </html>
17  )

5. Using a Mantine UI Component on page.tsx

Because of how Mantine components work, they must be used inside Client Components in Next.js. To make a component a Client Component add the use client to the top of the file.

1// app/page.tsx
2'use client'
3import styles from './page.module.css'
4import { Button } from '@mantine/core';
6export default function Home() {
7  const handleClick = () => { console.log("Clicked") }
9  return (
10    <main className={styles.main}>
11        <Button onClick={handleClick}>
12          Settings
13        </Button>
14    </main>
15  )

If everything goes well, you should have a Mantine UI Button in your Next.js application built in the app directory. Load up your dev environment npm run dev, and ensure it works!

Moving forward, any component you build that uses Mantine UI elements will need the use client directive. It’s best to keep these as small and single-purpose as possible so you don’t need use client in every file. Try to take advantage of the default Server Components whenever possible.

Tracking Production Support of Mantine in Next.js 13

Much work is being done to add better and easier support of UI component libraries in the new Next.js 13 app directory architecture. Below are the GitHub issues you can track to keep up with the latest changes and support for Next.js 13 in Mantine and Emotion.

Mantine with Next.js 13 app dir Issue #2815

Emotion: Plans to support Next.js 13 - /app directory Issue #2928