Server side rendering

This guide will help you get started with server side rendering with Next.js, Gatsby or your own server.

Next.js

Next.js example source code

In pages/_document.jsx setup getInitialProps to collect sheets with JssProvider:

import Document, { Html, Head, Main, NextScript } from 'next/document';
import { SheetsRegistry, JssProvider, createGenerateId } from 'react-jss';
export default class _Document extends Document {
static async getInitialProps(ctx) {
const registry = new SheetsRegistry();
const generateId = createGenerateId();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
(
<JssProvider registry={registry} generateId={generateId}>
<App {...props} />
</JssProvider>
),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<style id="mantine-ssr-styles">{registry.toString()}</style>
</>
),
};
}
render() {
return (
<Html>
<Head>
<link rel="icon" href="link to favicon" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

In pages/_app.jsx removed styles generated on server with useEffect and add MantineProvider in case you decide to change theme:

import React, { useEffect } from 'react';
import Head from 'next/head';
import { MantineProvider } from '@mantine/core';
export default function App(props) {
const { Component, pageProps } = props;
useEffect(() => {
const jssStyles = document.getElementById('mantine-ssr-styles');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<>
<Head>
<title>Mantine next example</title>
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width" />
</Head>
<MantineProvider
theme={{
/** Put your mantine theme override here */
colorScheme: 'dark',
}}
>
<Component {...pageProps} />
</MantineProvider>
</>
);
}

Known issues with Next.js

react-jss during ssr shows warning:

Warning: [JSS] Rule is not linked. Missing sheet option "link: true".

This warning is a bug and described in this issue. It would not impact styles and Mantine components in any way.

Gatsby

Gatsby example source code

Install gatsby-plugin-jss:

npm install gatsby-plugin-jss

Add gatsby-plugin-jss to your gatsby-config.js:

plugins: [`gatsby-plugin-jss` /* other plugins */];

Wrap your layout component with MantineProvider (skip this step if you stick with default theme):

import React from 'react';
import { MantineProvider } from '@mantine/core';
const Layout = ({ children }) => {
return (
<MantineProvider theme={{ fontFamily: 'Verdana, sans-serif' }}>
<main>{children}</main>
</MantineProvider>
);
};
export default Layout;

Your own server

Follow instruction on react-jss site.

Setup JssProvider on server:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { JssProvider, SheetsRegistry, createGenerateId } from 'react-jss';
import App from './App';
export default function render(req, res) {
const sheets = new SheetsRegistry();
const generateId = createGenerateId();
const body = renderToString(
<JssProvider registry={sheets} generateId={generateId}>
<App />
</JssProvider>
);
return res.send(
renderToString(
<html lang="en">
<head>
<style type="text/css" id="mantine-ssr-styles">
{sheets.toString()}
</style>
</head>
<body>{body}</body>
</html>
)
);
}

In your App component use MantineProvider and remove styles generated on server with useEffect hook

import React, { useEffect } from 'react';
import { MantineProvider } from '@mantine/core';
export default function App(props) {
const { Component, pageProps } = props;
useEffect(() => {
const jssStyles = document.getElementById('mantine-ssr-styles');
if (jssStyles) {
jssStyles.parentElement.removeChild(jssStyles);
}
}, []);
return (
<MantineProvider
theme={{
/** Put your mantine theme override here */
colorScheme: 'dark',
}}
>
<div>My app</div>
</MantineProvider>
);
}