How to Setup Next App, and MUI5 with Typescript
Tags: react, typescript, nextjs
Published: 2022-01-16 18:38:52

## Introduction

[**Next.js**](https://nextjs.org/) is a JavaScript open-source framework built on top of Node.js that enables you to build superfast and extremely user-friendly static websites, as well as web applications using React. React documentation mentions Next.js among "Recommended Toolchains" advising it to developers as a solution when "building a server-rendered website with Node.js.
&nbsp;


[**Material**](https://mui.com/)  UI is an open-source, front-end framework for React components that has 60,500 plus stars on Github. It is built using Less. Less (stands for Leaner Style Sheets), is a backward-compatible language extension for CSS. Material UI is based on Google’s Material Design to provide a high-quality, digital experience while developing front-end graphics. Material Design focuses on providing bold and crisp designs – it builds textures by focusing on how the components cast shadows and reflect light.
&nbsp;



**TypeScript** adds additional syntax to JavaScript to support a tighter integration with your editor. Catch errors early in your editor. TypeScript code converts to JavaScript, which runs anywhere JavaScript runs: In a browser, on Node.js or Deno, and in your apps.
&nbsp;


##Installation 
Before we get started, let’s confirm that we have Nodejs  installed on our machine by running the following command on our terminal:
```
node --version
```
and also run the following command to check if NPM installed on our computer
```
npm --version
```
If this returns an error, click [here ](https://nodejs.org/en/download/)to download and install Nodejs on your local machine. Nodejs installation comes with NPM by default, which we’ll be using to install the packages need for this tutorial.
&nbsp;
##step 1
With Nodejs and NPM installed, let’s begin by installing Nextjs and Typescript by running the following command on our terminal:

```
npx create-next-app@latest  --ts
```
You will be asked, "What is your project named?"  Type in the name you want to give the project and click enter
&nbsp;

##Step 2
cd into the directory,  and type the following command to open the project in VScode:

```
code .
```
we don't need to worry about the Typescript setup because the project has come with Typescript setup. let move on to the next step.

&nbsp;
##step 3
let install Material UI by typing the following command on our terminal

```
npm install @mui/material @emotion/react @emotion/styled
```
 we need to configure Nextjs to work with Material UI 

&nbsp;
##step 4
let create createEmotionCache.ts to configure emotion  to work with material  by typing the following command on your terminal

```
touch createEmotionCache.ts`
```
copy the following code into the createEmotionCache.ts

```
import createCache from '@emotion/cache';
 const createEmotionCache = () => {
  return createCache({ key: 'css' });
};
export default createEmotionCache;
```
&nbsp;
##step 5
create a file for Material UI theme, for this tutorial, name the file **theme.ts**
and copy the following code to the file. to learn more about the Material UI theme click [here](https://mui.com/customization/theming/)
```
import { createTheme } from '@mui/material/styles';
import { red } from '@mui/material/colors';

const theme = createTheme({
    palette: {
    primary: {
      main: '#556cd6',
    },
    secondary: {
      main: '#19857b',
    },
    error: {
      main: red.A400,
    },
  },
});
export default theme;
```
&nbsp;
##step 6
We will be extending the document and injecting the server-side rendered styles into the head. To override that default behavior, you must create a file at ./pages/_document.tsx where you can extend the Document class. copy the following code to the file
```
import * as React from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import theme from '../styles/theme';
import createEmotionCache from '../lib/createEmotionCache';

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

  const { renderPage: originalRenderPage } = ctx;

  // You can consider sharing the same emotion cache between all the SSR requests to speed up performance.
  // However, be aware that it can have global side effects.
  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  ctx.renderPage = () =>
    originalRenderPage({
      // eslint-disable-next-line react/display-name
      enhanceApp: (App: any) => (props) =>
        <App emotionCache={cache} {...props} />,
    });

  const initialProps = await Document.getInitialProps(ctx);
  // This is important. It prevents emotion to render invalid HTML.
  // See https://github.com/mui-org/material-ui/issues/26561#issuecomment-855286153
  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,
    ],
  };
};

```
&nbsp;

##step 7
we also need to wrap material UI with the app component,  let copy the following lines of code to _app.ts file inside the page folder.

```
import * as React from 'react';
import Head from 'next/head';
import { AppProps } from 'next/app';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { CacheProvider, EmotionCache } from '@emotion/react';
import theme from '../styles/theme';
import createEmotionCache from '../../src/lib/createEmotionCache';

// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();

interface MyAppProps extends AppProps {
  emotionCache?: EmotionCache;
}

const App = (props: MyAppProps) => {
  const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
  return (
    <CacheProvider value={emotionCache}>
      <Head>
        <title>My page</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>
  );
};

export default App;

```