Self-hosted fonts with Next.js and Material UI
Tags: react, nextjs, tutorial, beginners
Published: 2022-01-25 14:15:22

A few days back, I needed to import some .woff2 files into my Next.js project and pass them to Material UI. It took me a while to figure out how to do it, so here is a quick step-by-step tutorial for everyone who needs it and my forgetful future self.

## 1. Get a fresh next.js project up and running
You know the drill: Run `npx create-next-app fonts`, cd into the new directory and run `npm run dev` to see the Next.js starter in your browser window on `localhost:3000`.

## 2. Install Material UI
Once you have your project open, install Material UI with `npm install @mui/material @emotion/react @emotion/styled` (see the [installation docs](https://mui.com/getting-started/installation/) for any questions you might have regarding the installation or if some time has passed since this tutorial was published).

## 3. Locate your font-files
Find the public folder inside the root of your project directory. You can put your fonts directly inside this folder, although I recommend creating a subfolder called fonts, especially if your project has the potential to grow a bit.

![I put my fonts inside a fonts directory inside the public directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/poua393ok4xb6or6on04.png)

I took a snapshot of my folder structure here: For now, my fonts have their folder and everything else is just dumped inside the public folder since I don't have many static files for now.
 
## 4. Use your font inside CSS
Now you have to give your CSS access to your font, which you do by using the `font-face` rule. This is an instruction for your CSS to get the font from where you point it to, similar to the src attribute of an img tag.

The source can be inside the project or you can instruct the code to download the source from a CDN, Google Fonts being one of the more popular ones. (If you actually wanted to do that, [here](https://fonts.google.com/knowledge/using_type/using_web_fonts) are the instructions).

The font-face rule should be put inside a global CSS file: I put mine into the global.css Next.js had already created for me: you can find it inside styles > global.css

```CSS
@font-face {
  font-family: GothamMedium;
  src: url("/fonts/GothamRnd-Medium.woff2");
  format: ("woff2");
  font-display: swap;
}
```
You declare the name you will use for your font, in my case GothamMedium, the source URL, and the format. Be aware that the source URL is the relative path inside the public folder, so you shouldn't specify `public/` or something like that in the source and then be confused like me because the code didn't find the font.

The `font-display: swap` instruction is there to improve the performance of the page. It will tell the browser to render text right away with a system font and later repaint the content as soon as the custom font is loaded.

If you did everything right, you already should be able to use your font! Render hello world in a paragraph tag to see your loaded font in action:

![Hello world displayed with the self-hosted font](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d92oyfdhfbsghd797aq1.png)

## 5. Use your font inside MUI
As the last step, go inside the _app.js file and declare a theme and a ThemeProvider. Let's first declare an empty theme and look at the difference between the font used by the paragraph tag vs. the font used by the Typography component. 

```jsx
import "../styles/globals.css";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { Typography } from "@mui/material";

export let theme = createTheme({});

function MyApp({ Component }) {
  return (
        <ThemeProvider theme={theme}>
            <Typography>Hello world from typography component</Typography>
            <p>Hello world from paragraph tag</p>
            <Component {...pageProps} />
        </ThemeProvider>
  );
}

export default MyApp;
```
![MUI is not using the font yet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdtdw6ybaaa51d7c20n5.png)
 

So the font is already working, but Material UI has to pick it up yet. This can be done by simply declaring the font inside Material UI's theme object. Just use the same name for the font you used earlier in the CSS:

```javascript
export let theme = createTheme({
  typography: {
    fontFamily: "GothamMedium, sans-serif",
  }
});
```

Taking a look at the browser, we can now see that Material UI is already using the loaded font because both Hello worlds (is that the Hello world plural?) look the same.

![MUI is using the imported font](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqfqui950cgsjux6uc26.png)
 

That's it! I hope it helped and saved you some time. Have a great week!