7 min read

Create A Simple Production Website With Material-UI v5 & Nextjs.

We will learn how to build and deploy a simple restaurant website with Material-UI v5 & Nextjs in this tutorial.
Create A Simple Production Website With Material-UI v5 & Nextjs.

We will learn how to build and deploy a simple restaurant website with Material-UI v5 & Nextjs in this tutorial.

Prerequisite

  • Basic HTML, CSS & JavaScript
  • Basic Reactjs, useState, useEffect & JSX
  • Basic of Nextjs, at least go through Nextjs official tutorial once
  • Basic of Material-UI
  • Basic bash command
  • You've to know how to use VS Code or similar
  • Basic of styled component

📝 I'll write MUI5 to reduce the repetition of typing Material-UI v5.

Let's get started~

Tutorial 1: Set up MUI5 for Nextjs Project

Open the terminal of your choice.

cd toFolder/youWantToCreateTheProject
npx create-next-app mui5-next
cd mui5-next
npm install @material-ui/core@next @material-ui/icons@next @emotion/react @emotion/styled @emotion/cache @emotion/server

MUI5 is built on top of the emotion styled component library. You've to install all the dependencies packages.

The emotion's cache and server packages are required to set up MUI5 for the Nextjs project.

Open the project in VS Code:

code .

Customize _app.js for Nextjs & MUI5 Project

Open ./pages/_app.js

Add the code:

import * as React from "react";
import Head from "next/head";
import { ThemeProvider } from "@material-ui/core/styles";
import { CacheProvider } from "@emotion/react";
import { CssBaseline } from "@material-ui/core";
import createCache from "@emotion/cache";
import theme from "../styles/theme";
import "/styles/globals.css";

export const cache = createCache({ key: "css", prepend: true });

export default function MyApp(props) {
  const { Component, pageProps } = props;

  React.useEffect(() => {
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector("#jss-server-side");
    if (jssStyles) {
      jssStyles.parentElement.removeChild(jssStyles);
    }
  }, []);

  return (
    <CacheProvider value={cache}>
      <Head>
        <title>MUI 5 + Nextjs</title>
        <meta name="viewport" content="initial-scale=1, width=device-width" />
      </Head>
      <ThemeProvider theme={theme}>
        {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
        <CssBaseline />
        <Component {...pageProps} />
      </ThemeProvider>
    </CacheProvider>
  );
}
  • Set up the MUI theme context
  • Change the title to "MUI 5 + Nextjs"
  • Add CssBaseline to normalize the browser's User Agent Style sheets.
  • Set up server code to render MUI5 on the server.
  • Remain ./styles/global.css, we will add some global styles later.

In case you want to know more about the server-side rendering, visit https://next.material-ui.com/guides/server-rendering/

Customize _document.js for Nextjs & MUI5 Project

Create the file:

touch pages/_document.js

Add the code:

import * as React from "react";
import { CacheProvider } from "@emotion/react";
import createCache from "@emotion/cache";
import Document, { Html, Head, Main, NextScript } from "next/document";
import createEmotionServer from "@emotion/server/create-instance";
import theme from "../styles/theme";

const getCache = () => {
  const cache = createCache({ key: "css", prepend: true });
  cache.compat = true;

  return cache;
};

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <Head>
          {/* PWA primary color */}
          <meta name="theme-color" content={theme.palette.primary.main} />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with static-site generation (SSG).
MyDocument.getInitialProps = async (ctx) => {
  // Resolution order
  //
  // On the server:
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. document.getInitialProps
  // 4. app.render
  // 5. page.render
  // 6. document.render
  //
  // On the server with error:
  // 1. document.getInitialProps
  // 2. app.render
  // 3. page.render
  // 4. document.render
  //
  // On the client
  // 1. app.getInitialProps
  // 2. page.getInitialProps
  // 3. app.render
  // 4. page.render

  // Render app and page and get the context of the page with collected side effects.
  const originalRenderPage = ctx.renderPage;

  const cache = getCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  ctx.renderPage = () =>
    originalRenderPage({
      // Take precedence over the CacheProvider in our custom _app.js
      enhanceComponent: (Component) => (props) =>
        (
          <CacheProvider value={cache}>
            <Component {...props} />
          </CacheProvider>
        ),
    });

  const initialProps = await Document.getInitialProps(ctx);
  const emotionStyles = extractCriticalToChunks(initialProps.html);
  const emotionStyleTags = emotionStyles.styles.map((style) => (
    <style
      data-emotion={`${style.key} ${style.ids.join(" ")}`}
      key={style.key}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: style.css }}
    />
  ));

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [
      ...React.Children.toArray(initialProps.styles),
      ...emotionStyleTags,
    ],
  };
};
  • Feel free to delete all the comments. I leave the comment here so that people reading this article can read them as well.
  • MUI5 is using Roboto font. It's important to include the Roboto font here.
  • All the _app.js & _document.js code are copy from the example provided by MUI team. Check out the example https://github.com/mui-org/material-ui/tree/next/examples/nextjs
  • I had removed the "ServerStyleSheets" code.

In case you want to know why I removed the code, you can check out the MUI discussion with the link https://github.com/mui-org/material-ui/pull/26567

Customize the theme colour & responsive font size

Create the file:

touch styles/theme.js

Add the code:

import { createTheme, responsiveFontSizes } from "@material-ui/core/styles";
import { deepPurple, amber } from "@material-ui/core/colors";

// Create a theme instance.
let theme = createTheme({
  palette: {
    primary: deepPurple,
    secondary: amber,
  },
});

theme = responsiveFontSizes(theme);

export default theme;
  • Set up the theme to use deep purple as the primary colour and amber as the secondary colour.
  • Set up MUI responsive font based on the screen size.

Tell Nextjs to use Webpack 5

If you are using Nextjs 11, you can skip this step. Nextjs 11 use Webpack 5 by default.

Create the file:

touch next.config.js

add the code:

module.exports = {
  future: {
    webpack5: true,
  },
};

Initial the homepage

Open ./pages/index.js, replace the code with:-

import * as React from "react";
import Container from "@material-ui/core/Container";

const Homepage = () => {
  return (
    <Container maxWidth="sm">
    <h1>Home Page</h1>
    <p>lorem*15</p>
    </Container>
  );
};

export default Homepage;

Add 15 lines of lorem ipsum to the <p> tag. We will use it for scrolling purposes for next tutorial.

I am using Emmet to insert 15 lines of lorem ipsum with the shortcode as in the code.

import * as React from "react";
import Container from "@material-ui/core/Container";

const Homepage = () => {
  return (
    <Container maxWidth="sm">
      <h1>Home Page</h1>
      <p>
        Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eos,
        cupiditate! Odio, aliquam soluta vel, eum illum corrupti incidunt nobis
        porro mollitia itaque reiciendis. Aut, minus dolore! Delectus pariatur
        praesentium dolorem? In at, quibusdam vero eligendi provident veritatis
        ipsam suscipit nisi similique nulla est magni harum. Cumque maiores eos
        alias, aperiam ea deleniti voluptatem culpa a perferendis accusantium,
        necessitatibus velit laborum. Molestias, reprehenderit accusantium. Ad
        ipsa maiores, animi labore est voluptate eos aperiam iste adipisci sed
        dolor consequatur dolore provident tenetur ipsum! Velit laudantium
        excepturi accusantium numquam, similique nemo repellat impedit.
        Reiciendis illo quibusdam atque possimus aliquid. Illo in voluptatum
        nostrum quia nam fugit ipsa enim hic, eius sit qui recusandae dolorem
        quis dolor ut deleniti est possimus. Fugiat, aliquam quam. Itaque
        officiis culpa laborum voluptatum vel exercitationem temporibus, eos ad,
        ab eum inventore, hic quaerat ea cumque dignissimos dolorem maxime.
        Adipisci illo aspernatur eum. Minus, amet pariatur. Culpa, ratione
        expedita. Nemo doloribus dignissimos, deleniti sit veniam quae deserunt
        a nam sed, voluptas officia est recusandae consectetur exercitationem
        omnis? Neque impedit aspernatur tempora iusto distinctio nam amet
        recusandae inventore culpa eligendi! Sapiente accusantium aut animi eos
        iusto officia ipsum exercitationem illo quae, cumque quidem, nemo amet
        ad dicta fugit laboriosam mollitia soluta ratione corrupti maxime odit.
        Ipsum tenetur architecto vel ullam. Hic at, veritatis dolore, beatae
        totam amet alias unde odit veniam dolorum eos molestias quidem quo
        explicabo asperiores libero assumenda nulla velit nihil. Rerum error
        culpa cum voluptatibus beatae magnam? Repudiandae ratione iure,
        similique rerum dolore consectetur animi vitae qui delectus pariatur
        sapiente atque eos quaerat sed consequatur, quo suscipit optio harum
        aliquam adipisci vero. Nihil neque nisi eius. Laborum. Voluptatem
        voluptate officia numquam ut quae. Quod facilis pariatur in nostrum cum
        quidem at nesciunt fugiat est unde enim commodi, animi nihil, recusandae
        rerum ducimus sint qui assumenda distinctio id! Natus ea fugit molestiae
        nostrum! Obcaecati nisi itaque harum. Officia temporibus nobis
        repellendus beatae dolorem tempore accusamus! Quas debitis quos incidunt
        dolore aliquam, quam assumenda alias, totam omnis aspernatur saepe? Non
        debitis ab quis inventore vero. Possimus dicta labore quibusdam
        consequatur incidunt ea molestias fugit tenetur facere autem reiciendis
        animi amet, eligendi nobis impedit sunt consectetur deserunt doloremque
        nisi! Minus. Accusamus nam a soluta porro repudiandae quis at cupiditate
        ad impedit aperiam recusandae blanditiis ut enim repellendus velit qui
        cumque alias doloribus, accusantium voluptas quam eius! Consequuntur
        velit commodi minima. Saepe magnam fugit est et! Vel cumque modi itaque
        maiores vitae id, esse autem provident necessitatibus eius porro fuga,
        quod laborum, veritatis eum repellendus voluptatem aliquam ad
        perferendis quasi corrupti? Voluptates blanditiis earum optio omnis
        consectetur sapiente? Aliquid, expedita distinctio enim quos quis autem
        totam blanditiis ducimus laborum temporibus non. Repellat eaque aliquid
        perspiciatis fuga iste nam! Ut, iusto suscipit.
      </p>
    </Container>
  );
};

export default Homepage;

Remove unused style

Remove the file:

rm styles/Home.module.css

Well, we successfully initial a Nextjs & MUI5's project

Next~

We are going to build a Header component

Build Header Component With Nextjs & Material-UI v5
If you direct land on this page from searches, you may want to visit:- Tutorial 1: Set up MUI5 for Nextjs ProjectTutorial 2: You’re hereTutorial 2: Top Navigation HeaderWe’re building a top navigation bar with some modern features:- Hide the navigation bar on scrolling down and appear again

Feel free to tweet me if you have any feedback, improvement, suggestion or error.

Something to say about this tutorial? Comment on the Tweet below: