<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Next.js Archives | DMC, Inc.</title>
	<atom:link href="https://static.dmcinfo.com/blog/tag/next-js-2/feed/index.xml" rel="self" type="application/rss+xml" />
	<link></link>
	<description></description>
	<lastBuildDate>Thu, 27 Aug 2026 16:09:32 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.2</generator>

<image>
	<url>https://static.dmcinfo.com/wp-content/uploads/2025/04/site-icon-150x150.png</url>
	<title>Next.js Archives | DMC, Inc.</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Next.js 16 + Material UI Setup Guide for App Router + RSC: Dev Diary #2</title>
		<link>https://static.dmcinfo.com/blog/44831/material-ui-nextjs-16-app-router/</link>
		
		<dc:creator><![CDATA[Christopher Olsen]]></dc:creator>
		<pubDate>Mon, 01 Jun 2026 11:00:00 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[User Interface Design]]></category>
		<category><![CDATA[Next.js]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=44831</guid>

					<description><![CDATA[<p>In Part 1 of this two-part series, we walked through scaffolding a brand-new React application with Next.js. The result was a bare bones application with no styling to speak of. Early in any web application project, you have an important decision to make: are you going to build the look and feel of your app [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/44831/material-ui-nextjs-16-app-router/">Next.js 16 + Material UI Setup Guide for App Router + RSC: Dev Diary #2</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In <a href="https://static.dmcinfo.com/blog/41208/building-a-dba-dashboard-with-react-and-next-js-part-1/">Part 1</a> of this two-part series, we walked through scaffolding a brand-new React application with Next.js. The result was a bare bones application with no styling to speak of. Early in any web application project, you have an important decision to make: are you going to build the look and feel of your app from scratch with custom CSS and JavaScript, or are you going to leverage a third-party solution to achieve a more professional-looking UI than you would with a custom solution and with less development effort? Most people choose the latter, and we will too.</p>



<p class="wp-block-paragraph" style="padding-bottom:var(--wp--preset--spacing--20)">At DMC, our preferred UI library is Material UI, a component library maintained by Google. I first used Material UI nearly a decade ago, before it even reached version 1.0. Since then, the library has evolved significantly and now includes first-class support for Next.js and React Server Components. In this post, we&#8217;ll walk through how to add Material UI to a new Next.js 16 application. At the time of writing, Material UI v9.0.0 is the version in use.</p>



<h2 class="wp-block-heading" id="h-installing-the-npm-packages-for-material-ui">Installing the NPM Packages for Material UI</h2>



<p class="wp-block-paragraph">First, run the following command to install the core Material UI packages using Yarn:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>yarn add @mui/material @emotion/react @emotion/styled


</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">yarn add @mui/material @emotion/react @emotion/styled</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The Material UI documentation recommends installing <code>@fontsource/roboto</code> to use the Roboto font in your application. However, &nbsp;at the time of writing this post, that package causes the TypeScript server in my project to crash, resulting in the loss of IntelliSense support in Visual Studio Code. Because of this, I recommend skipping that package. Later in this post, we’ll import the Roboto font using a different approach.</p>



<p class="wp-block-paragraph">Next, run the following command to install the packages required to integrate Material UI with Next.js App Router:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>yarn add @mui/material-nextjs @emotion/cache


</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">yarn add @mui/material-nextjs @emotion/cache</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading" id="h-setting-up-a-material-ui-theme" style="padding-top:var(--wp--preset--spacing--30)">Setting Up a Material UI Theme</h2>



<p class="wp-block-paragraph">One of Material UI&#8217;s most useful features is its customizable themes. Material UI includes a default theme that can be extensively customized—everything from spacing, color palettes, and even border radius can be modified based on your design sensibilities.</p>



<p class="wp-block-paragraph">For this application, we&#8217;ll primarily use the default &nbsp;Material UI theme while enabling built-in light/dark mode functionality. We can initialize the theme using the <code>createTheme()</code> function:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// src/theme.tsx
"use client";
import { createTheme } from "@mui/material/styles";

const theme = createTheme({
  typography: {
    fontFamily: "var(--font-roboto)",
  },
  cssVariables: {
    colorSchemeSelector: "class",
  },
  colorSchemes: {
    dark: true,
  },
});

export default theme;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// src/theme.tsx</span></span>
<span class="line"><span style="color: #CE9178">&quot;use client&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { createTheme } from </span><span style="color: #CE9178">&quot;@mui/material/styles&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> theme = </span><span style="color: #DCDCAA">createTheme</span><span style="color: #D4D4D4">({</span></span>
<span class="line"><span style="color: #D4D4D4">  typography: {</span></span>
<span class="line"><span style="color: #D4D4D4">    fontFamily: </span><span style="color: #CE9178">&quot;var(--font-roboto)&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  cssVariables: {</span></span>
<span class="line"><span style="color: #D4D4D4">    colorSchemeSelector: </span><span style="color: #CE9178">&quot;class&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">  colorSchemes: {</span></span>
<span class="line"><span style="color: #D4D4D4">    dark: </span><span style="color: #569CD6">true</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  },</span></span>
<span class="line"><span style="color: #D4D4D4">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export default theme;</span></span></code></pre></div>



<p class="wp-block-paragraph">This theme configuration does three things:</p>



<ol class="wp-block-list">
<li>Sets Roboto as the default font family for all Typography components.</li>



<li>Enables dark mode support. Light mode is enabled by default.</li>



<li>Enables CSS variables and configures the colorSchemeSelector to use CSS classes.</li>
</ol>



<p class="wp-block-paragraph">The final configuration helps prevent SSR flickering, which can occur because the server cannot detect a user’s preferred color mode during the initial render. With this setup, Material UI applies either a light or dark class to the &lt;html&gt; element on the client side and uses CSS variables to apply the appropriate theme colors. This approach provides a smoother transition between server-side rendering and client-side hydration while maintaining support for light and dark themes.</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img fetchpriority="high" decoding="async" width="912" height="520" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-1.png" alt="Screenshot of a JavaScript code snippet manages theme switching between light and dark modes for a webpage." class="wp-image-44851" style="width:850px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-1.png 912w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-1-300x171.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-1-768x438.png 768w" sizes="(max-width: 912px) 100vw, 912px" /></figure>



<figure class="wp-block-image aligncenter size-full is-resized"><img decoding="async" width="1055" height="292" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-2.png" alt="Image displays CSS code using the Material UI (mui) framework to style an app bar component when the application is in dark mode." class="wp-image-44852" style="aspect-ratio:3.6131774707757707;width:850px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-2.png 1055w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-2-300x83.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-2-1024x283.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-2-768x213.png 768w" sizes="(max-width: 1055px) 100vw, 1055px" /></figure>



<h2 class="wp-block-heading" id="h-color-mode-picker" style="padding-top:var(--wp--preset--spacing--30)">Color Mode Picker</h2>



<p class="wp-block-paragraph">Speaking of color mode (light/dark), it can be nice to offer users a way to switch between light mode and dark mode. With the way we&#8217;ve configured our theme, Material UI will automatically set the color mode based on the user&#8217;s system preference, set in their web browser. So if a user has configured &#8220;dark&#8221; mode in Chrome, for example, when they visit our application, they&#8217;ll automatically get the dark-mode version of our UI.</p>



<p class="wp-block-paragraph">Some users may want dark mode specifically for our application and light mode elsewhere, so to provide that flexibility, we&#8217;ll build a simple color mode selector. For this, we&#8217;ll use the tools Material UI provides, including input and label components, along with tools for customizing them.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// colorThemePicker.tsx
"use client";
import FormControl from "@mui/material/FormControl";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import { useColorScheme } from "@mui/material/styles";
import { FormLabel } from "@mui/material";

export default function ColorThemePicker() {
  const { mode, setMode } = useColorScheme();
  if (!mode) {
    return null;
  }
  const handleChange = (event: SelectChangeEvent) => {
    setMode(event.target.value as "system" | "light" | "dark");
  };

  return (
    &lt;FormControl
      sx={{
        display: "flex",
        flexDirection: "row",
        alignItems: "center",
        gap: 1,
      }}
    >
      &lt;FormLabel id="theme-select-label">Theme&lt;/FormLabel>
      &lt;Select
        labelId="theme-select-label"
        aria-labelledby="theme-select-label"
        id="theme-select"
        value={mode}
        label="Theme"
        onChange={handleChange}
        sx={{ minWidth: "10rem" }}
      >
        &lt;MenuItem value="system">System&lt;/MenuItem>
        &lt;MenuItem value="light">Light&lt;/MenuItem>
        &lt;MenuItem value="dark">Dark&lt;/MenuItem>
      &lt;/Select>
    &lt;/FormControl>
  );
}

</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// colorThemePicker.tsx</span></span>
<span class="line"><span style="color: #CE9178">&quot;use client&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import FormControl from </span><span style="color: #CE9178">&quot;@mui/material/FormControl&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import Select, { SelectChangeEvent } from </span><span style="color: #CE9178">&quot;@mui/material/Select&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import MenuItem from </span><span style="color: #CE9178">&quot;@mui/material/MenuItem&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { useColorScheme } from </span><span style="color: #CE9178">&quot;@mui/material/styles&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { FormLabel } from </span><span style="color: #CE9178">&quot;@mui/material&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export default function </span><span style="color: #DCDCAA">ColorThemePicker</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> { mode, setMode } = </span><span style="color: #DCDCAA">useColorScheme</span><span style="color: #D4D4D4">();</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> (!mode) {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> null;</span></span>
<span class="line"><span style="color: #D4D4D4">  }</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> handleChange = (event: SelectChangeEvent) =&gt; {</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">setMode</span><span style="color: #D4D4D4">(</span><span style="color: #9CDCFE">event</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">target</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">value</span><span style="color: #D4D4D4"> as </span><span style="color: #CE9178">&quot;system&quot;</span><span style="color: #D4D4D4"> | </span><span style="color: #CE9178">&quot;light&quot;</span><span style="color: #D4D4D4"> | </span><span style="color: #CE9178">&quot;dark&quot;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;FormControl</span></span>
<span class="line"><span style="color: #D4D4D4">      sx={{</span></span>
<span class="line"><span style="color: #D4D4D4">        display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">        flexDirection: </span><span style="color: #CE9178">&quot;row&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">        alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">        gap: </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">      }}</span></span>
<span class="line"><span style="color: #D4D4D4">    &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;FormLabel id=</span><span style="color: #CE9178">&quot;theme-select-label&quot;</span><span style="color: #D4D4D4">&gt;Theme&lt;/FormLabel&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;Select</span></span>
<span class="line"><span style="color: #D4D4D4">        labelId=</span><span style="color: #CE9178">&quot;theme-select-label&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        aria-labelledby=</span><span style="color: #CE9178">&quot;theme-select-label&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        id=</span><span style="color: #CE9178">&quot;theme-select&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        value={mode}</span></span>
<span class="line"><span style="color: #D4D4D4">        label=</span><span style="color: #CE9178">&quot;Theme&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        onChange={handleChange}</span></span>
<span class="line"><span style="color: #D4D4D4">        sx={{ minWidth: </span><span style="color: #CE9178">&quot;10rem&quot;</span><span style="color: #D4D4D4"> }}</span></span>
<span class="line"><span style="color: #D4D4D4">      &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;MenuItem value=</span><span style="color: #CE9178">&quot;system&quot;</span><span style="color: #D4D4D4">&gt;System&lt;/MenuItem&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;MenuItem value=</span><span style="color: #CE9178">&quot;light&quot;</span><span style="color: #D4D4D4">&gt;Light&lt;/MenuItem&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;MenuItem value=</span><span style="color: #CE9178">&quot;dark&quot;</span><span style="color: #D4D4D4">&gt;Dark&lt;/MenuItem&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/Select&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/FormControl&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">I&#8217;ll explain this from the top down.</p>



<p class="wp-block-paragraph">We need a piece of state to track the user&#8217;s color mode selection: light, dark, or system (whatever they&#8217;ve selected in their browser settings). We also need a <strong>setter</strong> for that state so that we can update it based on the user&#8217;s actions. For that, we use a hook provided by Material UI: <a href="https://mui.com/material-ui/customization/dark-mode/#toggling-color-mode">useColorScheme()</a>. The <code>mode</code> returned by this hook is always undefined on the first render, so we handle that with a simple falsiness check:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>if(!mode) {
  return null;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4">(!mode) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> null;</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Next, we have our return statement where we declare the UI that this component should render. We&#8217;re making use of a few components from Material UI:</p>



<ul class="wp-block-list">
<li><a href="https://mui.com/material-ui/api/form-control/" target="_blank" rel="noreferrer noopener">FormControl</a></li>



<li><a href="https://mui.com/material-ui/api/form-label/" target="_blank" rel="noreferrer noopener">FormLabel</a></li>



<li><a href="https://mui.com/material-ui/react-select/" target="_blank" rel="noreferrer noopener">Select and MenuItem</a></li>
</ul>



<p class="wp-block-paragraph">The latter two are kind of self-explanatory if you have a basic background in HTML. FormControl is a nice-to-have component that manages some state related to the input element that it wraps, such as focused state, filled state, error state, required state, etc.</p>



<p class="wp-block-paragraph">Something I want to point out is the use of the sx prop on the FormControl component. This is a CSS-in-JS styling solution from Material UI, intended for one-off customization. Our application has precisely one color theme picker, so it easily fits the definition of a one-off customization. You can read more about this system in the <a href="https://mui.com/system/getting-started/usage" target="_blank" rel="noreferrer noopener">Material UI documentation</a>.</p>



<p class="wp-block-paragraph">The purpose served by our use of the <code>sx</code> prop here is to apply some flexbox CSS properties to our <code>FormControl</code> to make its child elements (the <code>FormLabel</code> and <code>Select</code> components) appear side by side instead of displaying the form label above the select component.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;FormControl
  sx={{
    display: "flex",
    flexDirection: "row",
    alignItems: "center",
    gap: 1,
  }}
>/
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;FormControl</span></span>
<span class="line"><span style="color: #D4D4D4">  sx={{</span></span>
<span class="line"><span style="color: #D4D4D4">    display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    flexDirection: </span><span style="color: #CE9178">&quot;row&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    gap: </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  }}</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;/</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Under the hood, a CSS selector is generated and applied to the rendered DOM element, and a &lt;style&gt; tag containing the corresponding CSS rule(s) is inserted into the DOM (see the screenshot below). So the result is similar to what we would get with a style sheet, except that it is generated at runtime after the initial HTML document is served to the client, which introduces some overhead for applying style rules.</p>



<figure class="wp-block-image aligncenter size-full is-resized"><img decoding="async" width="1377" height="158" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-3.png" alt="Image displaying a CSS style block generated by the Material-UI (MUI) library, specifically targeting a form label component." class="wp-image-44854" style="width:850px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-3.png 1377w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-3-300x34.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-3-1024x117.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-3-768x88.png 768w" sizes="(max-width: 1377px) 100vw, 1377px" /></figure>



<p class="wp-block-paragraph">In short, the trade-off is simpler code that&#8217;s easier to understand in exchange for a performance drop: up to 3x slower render time for 1,000 components, according to the documentation, which means you have to be rendering a lot of items to get a noticeable performance difference.</p>



<p class="wp-block-paragraph">Here&#8217;s what our color scheme picker looks like when rendered on the page:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="274" height="227" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-4.png" alt="Image displaying a drop-down menu for selecting a user interface Theme with &quot;Light&quot; selected." class="wp-image-44855" style="width:280px"/></figure>



<p class="wp-block-paragraph">And in dark mode:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="286" height="223" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-5.png" alt="Image displaying a drop-down menu for selecting a user interface Theme with &quot;Dark&quot; selected." class="wp-image-44856" style="width:280px"/></figure>



<p class="wp-block-paragraph">Not bad!</p>



<h2 class="wp-block-heading" id="h-client-components-and-building-a-nav-bar" style="padding-top:var(--wp--preset--spacing--30)">Client Components and Building a Nav Bar</h2>



<p class="wp-block-paragraph">Material UI has a <code>&lt;Link&gt;</code> component that makes it easy to render a professional-looking link on a web page. Since we&#8217;re using Next.js, we also want to use the <code>&lt;Link&gt;</code> component, which handles both server- and client-side routing. We&#8217;ll do this by providing the Next.js <code>&lt;Link&gt;</code> to the Material UI <code>&lt;Link&gt;</code> &#8220;component&#8221; prop, which essentially tells Material UI, &#8220;use this as the underlying component that you then attach all your fancy styles to.&#8221;</p>



<p class="wp-block-paragraph">However, with Next.js 16, this can result in an error: &#8220;Functions cannot be passed directly to Client Component&#8221;. As outlined in the Material UI documentation for Next.js integration, we can work around this by creating a client-side wrapper component for the Next.js <code>&lt;Link&gt;</code> component.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// src\app\_components\link.tsx
'use client';
import Link, { LinkProps } from 'next/link';

export default Link;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// src\app\_components\link.tsx</span></span>
<span class="line"><span style="color: #CE9178">&apos;use client&apos;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import Link, { LinkProps } from </span><span style="color: #CE9178">&apos;next/link&apos;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export default Link;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This will come in handy when building our top nav bar for this application, which we can get started on:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// src\app\_components\topNavBar.tsx 
import NextLink from "./link";
// (rest of import section omitted for brevity)

function TopNavBar() {
  return (
    &lt;AppBar position="static">
      &lt;Container
        maxWidth="xl"
        sx={{ display: "flex", justifyContent: "space-between" }}
      >
        &lt;Box
          sx={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
          }}
          component="nav"
        >
          &lt;Link component={NextLink} href="/" color="inherit" underline="none">
            &lt;Typography
              variant="body1"
              component="span"
              sx={{ display: "flex", alignItems: "center", gap: 0.5 }}
            >
              &lt;Icon>home&lt;/Icon>
              Home
            &lt;/Typography>
          &lt;/Link>
        &lt;/Box>
        &lt;ColorThemePicker />
      &lt;/Container>
    &lt;/AppBar>
  );
}

export default TopNavBar;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// src\app\_components\topNavBar.tsx </span></span>
<span class="line"><span style="color: #D4D4D4">import NextLink from </span><span style="color: #CE9178">&quot;./link&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #6A9955">// (rest of import section omitted for brevity)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">function </span><span style="color: #DCDCAA">TopNavBar</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;AppBar position=</span><span style="color: #CE9178">&quot;static&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;Container</span></span>
<span class="line"><span style="color: #D4D4D4">        maxWidth=</span><span style="color: #CE9178">&quot;xl&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        sx={{ display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">, justifyContent: </span><span style="color: #CE9178">&quot;space-between&quot;</span><span style="color: #D4D4D4"> }}</span></span>
<span class="line"><span style="color: #D4D4D4">      &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;Box</span></span>
<span class="line"><span style="color: #D4D4D4">          sx={{</span></span>
<span class="line"><span style="color: #D4D4D4">            display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">            justifyContent: </span><span style="color: #CE9178">&quot;space-between&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">            alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">          }}</span></span>
<span class="line"><span style="color: #D4D4D4">          component=</span><span style="color: #CE9178">&quot;nav&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          &lt;Link component={NextLink} href=</span><span style="color: #CE9178">&quot;/&quot;</span><span style="color: #D4D4D4"> color=</span><span style="color: #CE9178">&quot;inherit&quot;</span><span style="color: #D4D4D4"> underline=</span><span style="color: #CE9178">&quot;none&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;Typography</span></span>
<span class="line"><span style="color: #D4D4D4">              variant=</span><span style="color: #CE9178">&quot;body1&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">              component=</span><span style="color: #CE9178">&quot;span&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">              sx={{ display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">, alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">, gap: </span><span style="color: #B5CEA8">0.5</span><span style="color: #D4D4D4"> }}</span></span>
<span class="line"><span style="color: #D4D4D4">            &gt;</span></span>
<span class="line"><span style="color: #D4D4D4">              &lt;Icon&gt;home&lt;/Icon&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">              Home</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/Typography&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          &lt;/Link&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/Box&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;ColorThemePicker /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/Container&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/AppBar&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export default TopNavBar;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">For our top nav bar, we&#8217;re using the <a href="https://mui.com/material-ui/react-app-bar" target="_blank" rel="noreferrer noopener">AppBar</a> component from Material UI. This component looks great at the top of the screen and is an ideal place for top-level links, action buttons, menus, a login/logout button, etc.</p>



<p class="wp-block-paragraph">We&#8217;re putting a couple of elements into our top nav bar to start out:</p>



<ol class="wp-block-list">
<li>A list of links (currently just a link to the home page)</li>



<li>The color theme picker (this will eventually be replaced with a &#8220;hamburger button&#8221; that opens a modal dialog with settings/options)</li>
</ol>



<p class="wp-block-paragraph">I want these two components to be evenly spaced across the app bar, which sounds like a job for flexbox. To make that happen, I need to wrap them in a component, and <a href="https://mui.com/material-ui/react-container" target="_blank" rel="noreferrer noopener">Material UI&#8217;s Container</a> component fits the bill. I&#8217;m using Container because it&#8217;s a responsive component—we can use the <code>maxWidth</code> prop to define how <em>wide</em> it&#8217;s allowed to get based on the screen size. I want this nav bar to resize responsively all the way up to large desktop screens, so I&#8217;m providing &#8220;xl&#8221; as the value here &#8211; the width of the container will automatically adjust to smaller screen sizes.</p>



<p class="wp-block-paragraph">We can use the <code>sx</code> prop here to provide custom styling rules for this component—in this case, that would be using the &#8220;display&#8221; and &#8220;justifyContent&#8221; CSS properties to declare that the children of this component should be spaced evenly across the width of this container.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Container
  maxWidth="xl"
  sx={{ display: "flex", justifyContent: "space-between" }}
>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;Container</span></span>
<span class="line"><span style="color: #D4D4D4">  maxWidth=</span><span style="color: #CE9178">&quot;xl&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  sx={{ display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">, justifyContent: </span><span style="color: #CE9178">&quot;space-between&quot;</span><span style="color: #D4D4D4"> }}</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">To follow HTML best practices, we want to wrap our navigation links in a semantic <code>&lt;nav&gt;</code> element. But we also want to make sure that the links themselves are evenly spaced, so we need to apply some CSS rules to this <code>&lt;nav&gt;</code> element. The best way to accomplish this with Material UI is to use the generic <a href="https://mui.com/material-ui/react-box/" target="_blank" rel="noreferrer noopener">Box</a> component.</p>



<p class="wp-block-paragraph">Whenever you need to wrap other components with a containing element and apply style rules to it, <code>&lt;Box&gt;</code> is the go-to component. And we can tell Material UI which HTML element to render in the DOM by using the component prop, so we&#8217;ll pass the value &#8220;nav&#8221; to that prop to ensure it renders as a proper nav element. And again, we&#8217;re using the sx prop to define some basic flexbox properties and ensure that our link elements inside this box are spaced evenly and positioned nicely.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Box
  sx={{
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
  }}
  component="nav"
>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;Box</span></span>
<span class="line"><span style="color: #D4D4D4">  sx={{</span></span>
<span class="line"><span style="color: #D4D4D4">    display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    justifyContent: </span><span style="color: #CE9178">&quot;space-between&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  }}</span></span>
<span class="line"><span style="color: #D4D4D4">  component=</span><span style="color: #CE9178">&quot;nav&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">To start with, we&#8217;re going to only have one link in our nav bar: &#8220;Home&#8221;. The simplest version of this would just be to use Material UI&#8217;s Link component, pass my wrapper for the Next.js Link to the &#8220;component&#8221; prop, and, of course, set href to &#8220;/&#8221;. Like the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Link component={NextLink} href="/" color="inherit" underline="none">
  Home
&lt;/Link>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;Link component={NextLink} href=</span><span style="color: #CE9178">&quot;/&quot;</span><span style="color: #D4D4D4"> color=</span><span style="color: #CE9178">&quot;inherit&quot;</span><span style="color: #D4D4D4"> underline=</span><span style="color: #CE9178">&quot;none&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  Home</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/Link&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">But I also want to add a nifty little house icon to this link. Because I want this link to be inviting: &#8220;Come on home, you&#8217;re tired, and we have a nice fire going. You can take off your socks and cozy up by the fireplace with some hot cocoa and a grilled cheese sandwich.&#8221;</p>



<p class="wp-block-paragraph">Material UI makes that easy with its <a href="https://mui.com/material-ui/icons/" target="_blank" rel="noreferrer noopener">Icon</a> component. You can choose SVG or Font for the icons. To get off to a quick and easy start, I recommend the Font option. Later in this post, I&#8217;ll show how to enable that, but here&#8217;s what it&#8217;s going to look like in this component:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Link component={NextLink} href="/" color="inherit" underline="none">
  &lt;Icon>home&lt;/Icon>
  Home
&lt;/Link>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;Link component={NextLink} href=</span><span style="color: #CE9178">&quot;/&quot;</span><span style="color: #D4D4D4"> color=</span><span style="color: #CE9178">&quot;inherit&quot;</span><span style="color: #D4D4D4"> underline=</span><span style="color: #CE9178">&quot;none&quot;</span><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;Icon&gt;home&lt;/Icon&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  Home</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/Link&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">This ends up looking like the following when rendered on the page:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="188" height="74" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-6.png" alt="Screenshot of &quot;home&quot; link and &quot;home&quot; icon. The icon is positioned awkwardly off-center, making it look crooked." class="wp-image-44860" style="aspect-ratio:2.540772532188841;width:175px;height:auto"/></figure>



<p class="wp-block-paragraph">Oops! That icon is crooked! Or more accurately, it&#8217;s not vertically centered, so it looks awkward next to the text &#8220;Home&#8221;. We&#8217;ll fix that by applying some flexbox styling to the Link component:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;Link
  component={NextLink}
  href="/"
  color="inherit"
  underline="none"
  sx={{ display: "flex", alignItems: "center", gap: "0.5rem" }}
>
  &lt;Icon>home&lt;/Icon>
  Home
&lt;/Link>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;Link</span></span>
<span class="line"><span style="color: #D4D4D4">  component={NextLink}</span></span>
<span class="line"><span style="color: #D4D4D4">  href=</span><span style="color: #CE9178">&quot;/&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  color=</span><span style="color: #CE9178">&quot;inherit&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  underline=</span><span style="color: #CE9178">&quot;none&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  sx={{ display: </span><span style="color: #CE9178">&quot;flex&quot;</span><span style="color: #D4D4D4">, alignItems: </span><span style="color: #CE9178">&quot;center&quot;</span><span style="color: #D4D4D4">, gap: </span><span style="color: #CE9178">&quot;0.5rem&quot;</span><span style="color: #D4D4D4"> }}</span></span>
<span class="line"><span style="color: #D4D4D4">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;Icon&gt;home&lt;/Icon&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  Home</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/Link&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">The result looks so much better!</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="131" height="58" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-7.png" alt="Screenshot of &quot;home&quot; link and &quot;home icon&quot;, vertically aligned to look neater." class="wp-image-44861" style="aspect-ratio:2.2589298319920936;object-fit:cover;width:175px"/></figure>



<p class="wp-block-paragraph">Finally, after the nav links themselves, we have the color theme picker. Altogether, our nav bar looks like the following screenshot:</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="1230" height="232" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-8.png" alt="Screenshot of top nav bar." class="wp-image-44863" style="aspect-ratio:5.30214424951267" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-8.png 1230w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-8-300x57.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-8-1024x193.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-8-768x145.png 768w" sizes="(max-width: 1230px) 100vw, 1230px" /></figure>



<p class="wp-block-paragraph">Not bad, at least to start.</p>



<h2 class="wp-block-heading" id="h-updating-the-root-layout" style="padding-top:var(--wp--preset--spacing--30)">Updating the Root Layout</h2>



<p class="wp-block-paragraph">Now we&#8217;re ready to update our root layout (/src/app/layout.tsx) to use Material UI in our application.</p>



<h3 class="wp-block-heading" id="h-roboto-font-set-up" style="padding-top:var(--wp--preset--spacing--30)">Roboto Font Set Up</h3>



<p class="wp-block-paragraph">To enable using the Roboto font as the default font for our app, we need to use <a href="https://nextjs.org/docs/app/getting-started/fonts" target="_blank" rel="noreferrer noopener">Next.js font optimization</a>. The result of this step is that we end up self-hosting the Roboto font from Google:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>const roboto = Roboto({
  weight: &#91;"300", "400", "500", "700"&#93;,
  subsets: &#91;"latin"&#93;,
  display: "swap",
  variable: "--font-roboto",
});
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> roboto = </span><span style="color: #DCDCAA">Roboto</span><span style="color: #D4D4D4">({</span></span>
<span class="line"><span style="color: #D4D4D4">  weight: &#91;</span><span style="color: #CE9178">&quot;300&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;400&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;500&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;700&quot;</span><span style="color: #D4D4D4">&#93;,</span></span>
<span class="line"><span style="color: #D4D4D4">  subsets: &#91;</span><span style="color: #CE9178">&quot;latin&quot;</span><span style="color: #D4D4D4">&#93;,</span></span>
<span class="line"><span style="color: #D4D4D4">  display: </span><span style="color: #CE9178">&quot;swap&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  variable: </span><span style="color: #CE9178">&quot;--font-roboto&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">});</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">With that set up, we can give our HTML (root) element a new CSS class that will help give every typography element the Roboto font:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;html lang="en" className={roboto.variable} suppressHydrationWarning>

</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;html lang=</span><span style="color: #CE9178">&quot;en&quot;</span><span style="color: #D4D4D4"> className={</span><span style="color: #9CDCFE">roboto</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">variable</span><span style="color: #D4D4D4">} suppressHydrationWarning&gt;</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Remember how we set up our theme with the following property?</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typography: {
  fontFamily: "var(--font-roboto)",
},
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">typography: {</span></span>
<span class="line"><span style="color: #D4D4D4">  fontFamily: </span><span style="color: #CE9178">&quot;var(--font-roboto)&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">},</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">That &#8220;var(&#8211;font-roboto)&#8221; element is a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Cascading_variables/Using_custom_properties" target="_blank" rel="noreferrer noopener">CSS variable</a>. When combined, these two things result in a CSS variable named &#8220;&#8211;font-roboto&#8221; that&#8217;s <em>scoped</em> to a CSS class that&#8217;s generated at runtime and inserted into the stylesheet. This CSS class is then assigned to the <code>&lt;html&gt;</code> element so that any element in our HTML document can use that CSS variable. And by utilizing the &#8220;fontFamily&#8221; property of the &#8220;typography&#8221; section of our theme, we ensure that every typography element (MUI or not) uses the value of that variable for its &#8220;font-family&#8221; CSS property.</p>



<p class="wp-block-paragraph">The following screenshots from Chrome dev tools demonstrate this in action:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="816" height="67" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-9.png" alt="HTML tag showing the dynamically-generated CSS class." class="wp-image-44875" style="width:850px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-9.png 816w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-9-300x25.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-9-768x63.png 768w" sizes="(max-width: 816px) 100vw, 816px" /></figure>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="552" height="101" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-10.png" alt="Screenshot showing the CSS variable &quot;--font-roboto&quot;" class="wp-image-44877" style="width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-10.png 552w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-10-300x55.png 300w" sizes="(max-width: 552px) 100vw, 552px" /></figure>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="543" height="234" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-11.png" alt="Screenshot of a CSS rule for a label component, with the &quot;font-family&quot; property set to &quot;var(--font-roboto)&quot;" class="wp-image-44878" style="width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-11.png 543w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-11-300x129.png 300w" sizes="(max-width: 543px) 100vw, 543px" /></figure>



<h3 class="wp-block-heading" id="h-material-icons-set-up" style="padding-top:var(--wp--preset--spacing--40)">Material Icons Set Up</h3>



<p class="wp-block-paragraph">We need to import the Material Icons font so that we can use icons in our app. The easiest way to do this is to get it from the CDN. We can use the <code>&lt;head&gt;</code> element in our root layout.tsx file to insert a stylesheet link into the HTML document, ensuring that the user&#8217;s browser downloads that font.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;head>
  &lt;link
    rel="stylesheet"
    href="https://fonts.googleapis.com/icon?family=Material+Icons"
  />
&lt;/head>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;head&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;link</span></span>
<span class="line"><span style="color: #D4D4D4">    rel=</span><span style="color: #CE9178">&quot;stylesheet&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    href=</span><span style="color: #CE9178">&quot;https://fonts.googleapis.com/icon?family=Material+Icons&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/head&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">There&#8217;s also an NPM package you can install to self-host the font, but as I said earlier, it seems to crash the TypeScript server when using Next.js 16, so we&#8217;ll use the CDN until that gets sorted out.</p>



<h3 class="wp-block-heading" id="h-approutercacheprovider" style="padding-top:var(--wp--preset--spacing--30)">AppRouterCacheProvider</h3>



<p class="wp-block-paragraph">For optimal performance, it&#8217;s best to wrap your application with Material UI&#8217;s AppRouterCacheProvider component. According to the <a href="https://mui.com/material-ui/integrations/nextjs/#configuration" target="_blank" rel="noreferrer noopener">documentation</a>, this component &#8220;is responsible for collecting the CSS generated by MUI System on the server, as Next.js is streaming chunks of the .html page to the client.&#8221;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;body>
  &lt;AppRouterCacheProvider>
    &lt;main>
      {children}
    &lt;/main>
  &lt;/AppRouterCacheProvider>
&lt;/body>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      {children}</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/body&gt;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading" id="h-themeprovider" style="padding-top:var(--wp--preset--spacing--30)">ThemeProvider</h3>



<p class="wp-block-paragraph">For our application to use our custom theme, we need to wrap our application with the ThemeProvider component from Material UI, and provide our custom theme to the &#8220;theme&#8221; prop:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import theme from "../theme";
// ...
&lt;body>
  &lt;AppRouterCacheProvider>
    &lt;ThemeProvider theme={theme}>
      &lt;main>
        {children}
      &lt;/main>
    &lt;/ThemeProvider>
  &lt;/AppRouterCacheProvider>
&lt;/body>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">import theme from </span><span style="color: #CE9178">&quot;../theme&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #6A9955">// ...</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;ThemeProvider theme={theme}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        {children}</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/ThemeProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/body&gt;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading" id="h-cssbaseline" style="padding-top:var(--wp--preset--spacing--30)">CssBaseline</h3>



<p class="wp-block-paragraph">The <a href="https://mui.com/material-ui/react-css-baseline" target="_blank" rel="noreferrer noopener">CssBaseline</a> component allows us to clear out some undesirable CSS rules that browsers tend to have enabled by default. For example, without this component, there would be a default &#8220;margin&#8221; rule for <code>&lt;html&gt;</code> and <code>&lt;body&gt;</code>, resulting in a space around our actual page. So, our AppBar would not stretch all the way to the edges of the page, which is a jarring look. See the following screenshot for an example of what that looks like:</p>



<figure class="wp-block-image size-full is-resized has-custom-border"><img decoding="async" width="426" height="242" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-12-1.png" alt="Screenshot of the margin that appears by default if CssBaseline isn't used." class="has-border-color has-custom-black-border-color wp-image-44882" style="border-width:1px;aspect-ratio:1.7553438063353077;object-fit:cover;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-12-1.png 426w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-12-1-300x170.png 300w" sizes="(max-width: 426px) 100vw, 426px" /></figure>



<p class="wp-block-paragraph">So to avoid this, we simply have to add the CssBaseline component to our root layout:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;body>
  &lt;AppRouterCacheProvider>
    &lt;ThemeProvider theme={theme}>
      &lt;CssBaseline />
      &lt;main>
        {children}
      &lt;/main>
    &lt;/ThemeProvider>
  &lt;/AppRouterCacheProvider>
&lt;/body>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;ThemeProvider theme={theme}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;CssBaseline /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        {children}</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/ThemeProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/body&gt;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">That makes the margin disappear, as we can see in this screenshot:</p>



<figure class="wp-block-image size-full is-resized has-custom-border"><img decoding="async" width="387" height="224" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-13.png" alt="Screenshot of app without the browser default margin, thanks to CssBaseline." class="has-border-color has-custom-black-border-color wp-image-44883" style="border-width:1px;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-13.png 387w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-13-300x174.png 300w" sizes="(max-width: 387px) 100vw, 387px" /></figure>



<h3 class="wp-block-heading" id="h-initcolorschemescript" style="padding-top:var(--wp--preset--spacing--30)">InitColorSchemeScript</h3>



<p class="wp-block-paragraph">The <a href="https://mui.com/material-ui/react-init-color-scheme-script/#introduction" target="_blank" rel="noreferrer noopener">InitColorSchemeScript</a> component, when rendered before any of our actual content, will cause a script to run that attaches an attribute (a CSS class in our case) to the <code>&lt;html&gt;</code> element, indicating whether to use light or dark mode, depending on user preference. This runs <em>before</em> React itself starts doing client-side rendering and hydration; the result is that we prevent a &#8220;flicker&#8221; that would otherwise occur because the color scheme is not the default that&#8217;s assumed during server-side render.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;body>
  &lt;AppRouterCacheProvider>
    &lt;ThemeProvider theme={theme}>
      &lt;CssBaseline />
      &lt;InitColorSchemeScript attribute="class" />
      &lt;main>
        {children}
      &lt;/main>
    &lt;/ThemeProvider>
  &lt;/AppRouterCacheProvider>
&lt;/body>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;ThemeProvider theme={theme}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;CssBaseline /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;InitColorSchemeScript attribute=</span><span style="color: #CE9178">&quot;class&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        {children}</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/ThemeProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/body&gt;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading" id="h-wrapping-app-contents-in-a-container-and-adding-the-nav-bar" style="padding-top:var(--wp--preset--spacing--30)">Wrapping App Contents in a Container and Adding the Nav Bar</h3>



<p class="wp-block-paragraph">To finish things up here, we&#8217;re going to wrap the child components (i.e., the contents of any given page) in a Container component so that they appear to be the same width as the content of our AppBar. Without this, the content of the app&#8217;s pages would stretch to the edge of the screen. See the following screenshot—it doesn&#8217;t look right.</p>



<figure class="wp-block-image size-full is-resized has-custom-border"><img decoding="async" width="470" height="212" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-14.png" alt="Screenshot of the web page's content stretching all the way to the edge of the browser window, making it wider than the nav bar's contents." class="has-border-color has-custom-black-border-color wp-image-44886" style="border-width:1px;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-14.png 470w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-14-300x135.png 300w" sizes="(max-width: 470px) 100vw, 470px" /></figure>



<p class="wp-block-paragraph">By wrapping <code>{children}</code> in a container and giving it <code>maxWidth</code> of &#8220;xl&#8221;, matching the approach used for the AppBar content, we ensure the entire application aligns cleanly and maintains a comfortable margin between the screen edge and the app’s content.</p>



<figure class="wp-block-image size-full is-resized has-custom-border"><img decoding="async" width="543" height="220" src="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-15.png" alt="Screenshot of the web page's content having the same margin from the edge of the screen as the nav bar's contents." class="has-border-color has-custom-black-border-color wp-image-44889" style="border-width:1px;width:500px" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-15.png 543w, https://static.dmcinfo.com/wp-content/uploads/2026/05/adding-material-ui-next.js-image-15-300x122.png 300w" sizes="(max-width: 543px) 100vw, 543px" /></figure>



<p class="wp-block-paragraph">We&#8217;ll also render our custom TopNavBar component <em>before</em> the container, so that the nav bar always appears at the top of the page, with the current web page being displayed beneath it.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&lt;body>
  &lt;AppRouterCacheProvider>
    &lt;ThemeProvider theme={theme}>
      &lt;CssBaseline />
      &lt;InitColorSchemeScript attribute="class" />
      &lt;main>
        &lt;TopNavBar />
        &lt;Container maxWidth="xl">{children}&lt;/Container>
      &lt;/main>
    &lt;/ThemeProvider>
  &lt;/AppRouterCacheProvider>
&lt;/body>
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">&lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;ThemeProvider theme={theme}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;CssBaseline /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;InitColorSchemeScript attribute=</span><span style="color: #CE9178">&quot;class&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;TopNavBar /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;Container maxWidth=</span><span style="color: #CE9178">&quot;xl&quot;</span><span style="color: #D4D4D4">&gt;{children}&lt;/Container&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/ThemeProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">&lt;/body&gt;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading" id="h-the-full-layout-tsx-file" style="padding-top:var(--wp--preset--spacing--30)">The Full layout.tsx File</h3>



<p class="wp-block-paragraph">Altogether, our layout.tsx file looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// src\app\layout.tsx
import type { Metadata } from "next";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v15-appRouter";
import { Roboto } from "next/font/google";
import { ThemeProvider } from "@mui/material/styles";
import theme from "../theme";
import { Container, CssBaseline, InitColorSchemeScript } from "@mui/material";
import TopNavBar from "./_components/topNavBar";

const roboto = Roboto({
  weight: &#91;"300", "400", "500", "700"&#93;,
  subsets: &#91;"latin"&#93;,
  display: "swap",
  variable: "--font-roboto",
});

export const metadata: Metadata = {
  title: "DBA Dashboard",
  description:
    "A dashboard UI for exploring the results from the SQL Server First Responder Kit stored procedures",
};

export default function RootLayout({
  children,
}: Readonly&lt;{
  children: React.ReactNode;
}>) {
  return (
    &lt;html lang="en" className={roboto.variable} suppressHydrationWarning>
      &lt;head>
        &lt;link
          rel="stylesheet"
          href="https://fonts.googleapis.com/icon?family=Material+Icons"
        />
      &lt;/head>
      &lt;body>
        &lt;AppRouterCacheProvider>
          &lt;ThemeProvider theme={theme}>
            &lt;CssBaseline />
            &lt;InitColorSchemeScript attribute="class" />
            &lt;main>
              &lt;TopNavBar />
              &lt;Container maxWidth="xl">{children}&lt;/Container>
            &lt;/main>
          &lt;/ThemeProvider>
        &lt;/AppRouterCacheProvider>
      &lt;/body>
    &lt;/html>
  );
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// src\app\layout.tsx</span></span>
<span class="line"><span style="color: #D4D4D4">import type { Metadata } from </span><span style="color: #CE9178">&quot;next&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { AppRouterCacheProvider } from </span><span style="color: #CE9178">&quot;@mui/material-nextjs/v15-appRouter&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { Roboto } from </span><span style="color: #CE9178">&quot;next/font/google&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { ThemeProvider } from </span><span style="color: #CE9178">&quot;@mui/material/styles&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import theme from </span><span style="color: #CE9178">&quot;../theme&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import { Container, CssBaseline, InitColorSchemeScript } from </span><span style="color: #CE9178">&quot;@mui/material&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">import TopNavBar from </span><span style="color: #CE9178">&quot;./_components/topNavBar&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> roboto = </span><span style="color: #DCDCAA">Roboto</span><span style="color: #D4D4D4">({</span></span>
<span class="line"><span style="color: #D4D4D4">  weight: &#91;</span><span style="color: #CE9178">&quot;300&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;400&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;500&quot;</span><span style="color: #D4D4D4">, </span><span style="color: #CE9178">&quot;700&quot;</span><span style="color: #D4D4D4">&#93;,</span></span>
<span class="line"><span style="color: #D4D4D4">  subsets: &#91;</span><span style="color: #CE9178">&quot;latin&quot;</span><span style="color: #D4D4D4">&#93;,</span></span>
<span class="line"><span style="color: #D4D4D4">  display: </span><span style="color: #CE9178">&quot;swap&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  variable: </span><span style="color: #CE9178">&quot;--font-roboto&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">});</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> metadata: Metadata = {</span></span>
<span class="line"><span style="color: #D4D4D4">  title: </span><span style="color: #CE9178">&quot;DBA Dashboard&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  description:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;A dashboard UI for exploring the results from the SQL Server First Responder Kit stored procedures&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">export default function </span><span style="color: #DCDCAA">RootLayout</span><span style="color: #D4D4D4">({</span></span>
<span class="line"><span style="color: #D4D4D4">  children,</span></span>
<span class="line"><span style="color: #D4D4D4">}: Readonly&lt;{</span></span>
<span class="line"><span style="color: #D4D4D4">  children: </span><span style="color: #9CDCFE">React</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">ReactNode</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}&gt;) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;html lang=</span><span style="color: #CE9178">&quot;en&quot;</span><span style="color: #D4D4D4"> className={</span><span style="color: #9CDCFE">roboto</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">variable</span><span style="color: #D4D4D4">} suppressHydrationWarning&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;head&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;link</span></span>
<span class="line"><span style="color: #D4D4D4">          rel=</span><span style="color: #CE9178">&quot;stylesheet&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">          href=</span><span style="color: #CE9178">&quot;https://fonts.googleapis.com/icon?family=Material+Icons&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/head&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          &lt;ThemeProvider theme={theme}&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;CssBaseline /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;InitColorSchemeScript attribute=</span><span style="color: #CE9178">&quot;class&quot;</span><span style="color: #D4D4D4"> /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">              &lt;TopNavBar /&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">              &lt;Container maxWidth=</span><span style="color: #CE9178">&quot;xl&quot;</span><span style="color: #D4D4D4">&gt;{children}&lt;/Container&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">            &lt;/main&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          &lt;/ThemeProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;/AppRouterCacheProvider&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/body&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;/html&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">We can also adjust the page.tsx (home page) component to be a bit more minimal, since it no longer needs to render its own <code>&lt;main&gt;</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">C</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// src\app\page.tsx
export default function Home() {
  return (
    &lt;>
      &lt;header>
        &lt;h1>DBA Dashboard&lt;/h1>
      &lt;/header>
      &lt;p>
        Welcome to the DBA Dashboard! There&apos;s not much here yet, but stay
        tuned for updates as we build out the UI for exploring the results from
        the SQL Server First Responder Kit stored procedures.
      &lt;/p>
    &lt;/>
  );
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// src\app\page.tsx</span></span>
<span class="line"><span style="color: #D4D4D4">export default function </span><span style="color: #DCDCAA">Home</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    &lt;&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;header&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        &lt;h1&gt;DBA Dashboard&lt;/h1&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;/header&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      &lt;p&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        Welcome to the DBA Dashboard! There</span><span style="color: #CE9178">&apos;s not much here yet, but stay</span></span>
<span class="line"><span style="color: #CE9178">        tuned for updates as we build out the UI for exploring the results from</span></span>
<span class="line"><span style="color: #CE9178">        the SQL Server First Responder Kit stored procedures.</span></span>
<span class="line"><span style="color: #CE9178">      &lt;/p&gt;</span></span>
<span class="line"><span style="color: #CE9178">    &lt;/&gt;</span></span>
<span class="line"><span style="color: #CE9178">  );</span></span>
<span class="line"><span style="color: #CE9178">}</span></span>
<span class="line"></span></code></pre></div>



<h2 class="wp-block-heading" id="h-conclusion" style="padding-top:var(--wp--preset--spacing--40)">Conclusion</h2>



<p class="wp-block-paragraph" style="padding-bottom:var(--wp--preset--spacing--40)">And that&#8217;s it! We&#8217;ve successfully set up Material UI with our Next.js 16 application—going forward, we can easily make every UI element we add to the app look professional with minimal effort. In the next post, we&#8217;ll get authentication set up&nbsp;using a library called Better Auth, along with Microsoft&#8217;s Entra ID authentication service.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step">Have an upcoming project? DMC can help you take the next step.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Take your project to the next level with engineering solutions from DMC. Learn more about our <a href="https://static.dmcinfo.com/services/application-development/">Application Development</a> solutions or contact us to get started today!</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/44831/material-ui-nextjs-16-app-router/">Next.js 16 + Material UI Setup Guide for App Router + RSC: Dev Diary #2</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Starting a DBA Dashboard with Next.js 16 and React: Dev Diary #1</title>
		<link>https://static.dmcinfo.com/blog/41208/building-a-dba-dashboard-with-react-and-next-js-part-1/</link>
		
		<dc:creator><![CDATA[Christopher Olsen]]></dc:creator>
		<pubDate>Mon, 04 May 2026 14:00:00 +0000</pubDate>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[React]]></category>
		<guid isPermaLink="false">https://static.dmcinfo.com/?p=41208</guid>

					<description><![CDATA[<p>React has been DMC&#8217;s JavaScript framework of choice for over 10 years. In recent years, we&#8217;ve been using it alongside Next.js to build maintainable, scalable, full-stack web applications. In this blog series, I&#8217;m going to demonstrate how to use React and Next.js to build a DBA dashboard that offers a variety of tools to spot [&#8230;]</p>
<p>The post <a href="https://static.dmcinfo.com/blog/41208/building-a-dba-dashboard-with-react-and-next-js-part-1/">Starting a DBA Dashboard with Next.js 16 and React: Dev Diary #1</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">React has been DMC&#8217;s JavaScript framework of choice for over 10 years. In recent years, we&#8217;ve been using it alongside Next.js to build maintainable, scalable, full-stack web applications. In this <a href="https://static.dmcinfo.com/blog/44831/material-ui-nextjs-16-app-router/">blog series</a>, I&#8217;m going to demonstrate how to use React and Next.js to build a DBA dashboard that offers a variety of tools to spot and troubleshoot performance or reliability issues with a SQL Server instance.</p>



<p class="wp-block-paragraph">I plan to use Better-Auth for authentication and Material UI as a UI component library, and of course, I&#8217;ll be using SQL Server (a.k.a. MSSQL). So, if you&#8217;d like to learn how to build a React app with Next.js, Better-Auth, Material UI, and MSSQL using Prisma ORM, I&#8217;m going to show you how to set it all up.</p>



<h2 class="wp-block-heading" id="h-scaffolding-a-next-js-app">Scaffolding <strong>a Next.js App</strong></h2>



<p class="wp-block-paragraph">The first step to building a Next.js app is to run the create-next-app CLI tool. First, make sure you&#8217;ve installed Node.js version 24 or later. Then, run <code>npx create-next-app@latest</code> the CLI tool and create the application. It presents us with the following options:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1054" height="955" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image.png" alt="" class="wp-image-41398" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image.png 1054w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-300x272.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1024x928.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-768x696.png 768w" sizes="(max-width: 1054px) 100vw, 1054px" /></figure>



<p class="wp-block-paragraph">I recommend the following options:</p>



<ol class="wp-block-list">
<li><strong>TypeScript</strong> &#8211; at DMC, we&#8217;ve used it for React applications since 2016 and have adopted it as a standard. TypeScript is a superset of JavaScript that adds strong typing so that, for example, you&#8217;ll get a compiler error if you try to assign an integer value to a string variable. Fully explaining TypeScript is outside of the scope of this article, but I strongly recommend using it for all React applications.</li>



<li><strong>ESLint</strong> &#8211; this is the gold standard linter for JavaScript/TypeScript, and you really can&#8217;t go wrong by choosing it.</li>



<li><strong>React Compiler</strong> &#8211; I have been very eager to try this out on a project ever since it was introduced to React. Among other things, this makes it so you don&#8217;t need to explicitly use the useMemo or useCallback hooks &#8211; the compiler will take care of those optimizations for you so that you can focus on building your app.</li>



<li><strong>src directory</strong> &#8211; this is a pretty standard setup for JavaScript/TypeScript applications.</li>



<li><strong>App Router</strong> &#8211; the alternative is Page Router, which is the legacy version of Next.js.</li>
</ol>



<p class="wp-block-paragraph">By default, the CLI tool gets us set up with a package-lock.json file, but I prefer to use Yarn as my package manager, so I like to delete that file and run <code>yarn install</code>. Then I keep the yarn.lock file in source control.</p>



<p class="wp-block-paragraph">The app scaffolded by the CLI tool can be run locally with the command <code>yarn dev</code>. Doing so shows me a placeholder home page that looks like the following:</p>



<figure class="wp-block-image size-full is-resized"><img decoding="async" width="1396" height="1138" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1.png" alt="" class="wp-image-41410" style="width:554px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1.png 1396w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1-300x245.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1-1024x835.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-1-768x626.png 768w" sizes="(max-width: 1396px) 100vw, 1396px" /></figure>



<p class="wp-block-paragraph">When I&#8217;m building a new app, the first thing I do is clear out all the scaffolded content, like that placeholder page and the accompanying CSS. Once I&#8217;ve finished that, layout.tsx file and page.tsx file scaffolded by the CLI looks like the following:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TSX</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// layout.tsx
import type { Metadata } from "next";

export const metadata: Metadata = {
  title: "DBA Dashboard",
  description:
    "A dashboard UI for exploring the results from the SQL Server First Responder Kit stored procedures",
};

export default function RootLayout({
  children,
}: Readonly&lt;{
  children: React.ReactNode;
}>) {
  return (
    &lt;html lang="en">
      &lt;body>{children}&lt;/body>
    &lt;/html>
  );
}

// page.tsx
export default function Home() {
  return (
    &lt;div>
      &lt;main>
        &lt;header>
          &lt;h1>DBA Dashboard&lt;/h1>
        &lt;/header>
        &lt;p>
          Welcome to the DBA Dashboard! There's not much here yet, but stay
          tuned for updates as we build out the UI for exploring the results
          from the SQL Server First Responder Kit stored procedures.
        &lt;/p>
      &lt;/main>
    &lt;/div>
  );
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// layout.tsx</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">type</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">Metadata</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;next&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">metadata</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">Metadata</span><span style="color: #D4D4D4"> = {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">title:</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;DBA Dashboard&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">description:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;A dashboard UI for exploring the results from the SQL Server First Responder Kit stored procedures&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">default</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">RootLayout</span><span style="color: #D4D4D4">({</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">children</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">}: </span><span style="color: #4EC9B0">Readonly</span><span style="color: #D4D4D4">&lt;{</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">children</span><span style="color: #D4D4D4">: </span><span style="color: #4EC9B0">React</span><span style="color: #D4D4D4">.</span><span style="color: #4EC9B0">ReactNode</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">}&gt;) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">html</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">lang</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;en&quot;</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">body</span><span style="color: #808080">&gt;</span><span style="color: #569CD6">{</span><span style="color: #9CDCFE">children</span><span style="color: #569CD6">}</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">body</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">html</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955">// page.tsx</span></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">default</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Home</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">div</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">main</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">header</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">h1</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">DBA Dashboard</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">h1</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">header</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">p</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          Welcome to the DBA Dashboard! There&apos;s not much here yet, but stay</span></span>
<span class="line"><span style="color: #D4D4D4">          tuned for updates as we build out the UI for exploring the results</span></span>
<span class="line"><span style="color: #D4D4D4">          from the SQL Server First Responder Kit stored procedures.</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">p</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">main</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">div</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">And here&#8217;s the resulting home page of our new Next.js app:</p>



<figure class="wp-block-image size-full is-resized has-custom-border"><img decoding="async" width="1164" height="1282" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-2.png" alt="" class="has-border-color has-custom-black-border-color wp-image-41411" style="border-width:1px;width:631px;height:auto" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-2.png 1164w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-2-272x300.png 272w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-2-930x1024.png 930w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-2-768x846.png 768w" sizes="(max-width: 1164px) 100vw, 1164px" /></figure>



<p class="wp-block-paragraph">You may notice a little circular &#8220;N&#8221; button at the lower left corner &#8211; that&#8217;s a widget that Next.js gives us when running locally in dev mode. (TODO: Give more details about this, probably a link to documentation. This feature is new to me &#8211; apparently it&#8217;s called a &#8220;devIndicator&#8221;).</p>



<h2 class="wp-block-heading" id="h-configuring-the-next-js-app">Configuring the Next.js App</h2>



<p class="wp-block-paragraph">At the start of a new project, I like to get off on the right foot with regard to linting. Our scaffolded app is set up for ESLint out of the box, so I can run <code>yarn lint</code> to check for violations, and there are quite a few!</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1416" height="628" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-3.png" alt="" class="wp-image-41412" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-3.png 1416w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-3-300x133.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-3-1024x454.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-3-768x341.png 768w" sizes="(max-width: 1416px) 100vw, 1416px" /></figure>



<p class="wp-block-paragraph">These violations are coming from files that were created by the CLI tool &#8211; I didn&#8217;t write this code. Because of that, I&#8217;d like to ignore these files when doing lint checks &#8211; to do that, I can add the &#8220;types&#8221; folder to the eslint.config.mjs file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">JavaScript</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
  ...nextVitals,
  ...nextTs,
  // Override default ignores of eslint-config-next.
  globalIgnores(&#91;
    // Default ignores of eslint-config-next:
    ".next/**",
    "out/**",
    "build/**",
    "next-env.d.ts",
    // Custom ignores:
    "types/**",
  &#93;),
]);

export default eslintConfig;</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> { </span><span style="color: #9CDCFE">defineConfig</span><span style="color: #D4D4D4">, </span><span style="color: #9CDCFE">globalIgnores</span><span style="color: #D4D4D4"> } </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;eslint/config&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">nextVitals</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;eslint-config-next/core-web-vitals&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #C586C0">import</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">nextTs</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">from</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;eslint-config-next/typescript&quot;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6">const</span><span style="color: #D4D4D4"> </span><span style="color: #4FC1FF">eslintConfig</span><span style="color: #D4D4D4"> = </span><span style="color: #DCDCAA">defineConfig</span><span style="color: #D4D4D4">([</span></span>
<span class="line"><span style="color: #D4D4D4">  ...</span><span style="color: #9CDCFE">nextVitals</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  ...</span><span style="color: #9CDCFE">nextTs</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955">// Override default ignores of eslint-config-next.</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">globalIgnores</span><span style="color: #D4D4D4">(&#91;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Default ignores of eslint-config-next:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;.next/**&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;out/**&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;build/**&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;next-env.d.ts&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955">// Custom ignores:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #CE9178">&quot;types/**&quot;</span><span style="color: #D4D4D4">,</span></span>
<span class="line"><span style="color: #D4D4D4">  &#93;),</span></span>
<span class="line"><span style="color: #D4D4D4">]);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">default</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">eslintConfig</span><span style="color: #D4D4D4">;</span></span></code></pre></div>



<p class="wp-block-paragraph">Now, if I run <code>yarn lint</code> again, it only raises one violation:</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1212" height="394" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-4.png" alt="" class="wp-image-41413" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-4.png 1212w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-4-300x98.png 300w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-4-1024x333.png 1024w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-4-768x250.png 768w" sizes="(max-width: 1212px) 100vw, 1212px" /></figure>



<p class="wp-block-paragraph">Looks like I forgot to use an HTML entity for that apostrophe in my hard-coded text. So I&#8217;ll just fix that:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:16px 0 0 16px;width:100%;text-align:left;background-color:#1e1e1e"><span style="background:#c7c7c7;padding:0.3rem 0.5rem 0.2rem;border-radius:1rem;font-size:0.8em;line-height:1;height:1.25rem;text-align:center;display:inline-flex;align-items:center;justify-content:center;color:#1e1e1e">TSX</span></span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>// page.tsx
export default function Home() {
  return (
    &lt;div>
      &lt;main>
        &lt;header>
          &lt;h1>DBA Dashboard&lt;/h1>
        &lt;/header>
        &lt;p>
          Welcome to the DBA Dashboard! There&apos;s not much here yet, but stay
          tuned for updates as we build out the UI for exploring the results
          from the SQL Server First Responder Kit stored procedures.
        &lt;/p>
      &lt;/main>
    &lt;/div>
  );
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">// page.tsx</span></span>
<span class="line"><span style="color: #C586C0">export</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">default</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">Home</span><span style="color: #D4D4D4">() {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> (</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">div</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">main</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">header</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">h1</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">DBA Dashboard</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">h1</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">header</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">p</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">          Welcome to the DBA Dashboard! There&apos;s not much here yet, but stay</span></span>
<span class="line"><span style="color: #D4D4D4">          tuned for updates as we build out the UI for exploring the results</span></span>
<span class="line"><span style="color: #D4D4D4">          from the SQL Server First Responder Kit stored procedures.</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">p</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">main</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">div</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">  );</span></span>
<span class="line"><span style="color: #D4D4D4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">After fixing that, ESLint raises no violations, so now we&#8217;re officially starting with a squeaky-clean codebase!</p>



<figure class="wp-block-image size-full"><img decoding="async" width="412" height="181" src="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-5.png" alt="" class="wp-image-41414" srcset="https://static.dmcinfo.com/wp-content/uploads/2026/02/image-5.png 412w, https://static.dmcinfo.com/wp-content/uploads/2026/02/image-5-300x132.png 300w" sizes="(max-width: 412px) 100vw, 412px" /></figure>



<p class="wp-block-paragraph" style="margin-bottom:var(--wp--preset--spacing--50)">In the next blog post, we&#8217;ll be adding a component library to our project: Material UI. A high-quality component library like Material UI makes it easy to build a professional-looking user interface for our dashboard.</p>



<div class="wp-block-group alignwide has-custom-light-blue-background-color has-background is-layout-flow wp-container-core-group-is-layout-dbd34961 wp-block-group-is-layout-flow" style="border-radius:20px;margin-top:var(--wp--preset--spacing--50);margin-bottom:var(--wp--preset--spacing--50);padding-top:var(--wp--preset--spacing--50);padding-right:0;padding-bottom:var(--wp--preset--spacing--50);padding-left:0">
<div class="wp-block-columns alignwide are-vertically-aligned-center is-layout-flex wp-container-core-columns-is-layout-43efaee5 wp-block-columns-is-layout-flex" style="padding-right:var(--wp--preset--spacing--60);padding-left:var(--wp--preset--spacing--60)">
<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:85%">
<h3 class="wp-block-heading has-text-align-left" id="h-have-an-upcoming-project-dmc-can-help-you-take-the-next-step">Have an upcoming project? DMC can help you take the next step.</h3>



<p class="has-text-align-left wp-block-paragraph" id="h-need-help-turning-ideas-into-outcomes-automation-project-to-the-next-level-contact-us-today-to-learn-more-about-our-solutions-and-how-we-can-help-you-achieve-your-goals">Take your project to the next level with engineering solutions from DMC. Learn more about our <a href="https://static.dmcinfo.com/services/application-development/" id="https://static.dmcinfo.com/services/application-development/">Application Development</a> solutions or contact us to get started today!</p>
</div>



<div class="wp-block-column is-vertically-aligned-center is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:15%">
<div class="wp-block-buttons is-horizontal is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-2236275c wp-block-buttons-is-layout-flex">
<div class="wp-block-button is-style-fill"><a class="wp-block-button__link has-base-contrast-color has-text-color has-link-color wp-element-button" href="https://static.dmcinfo.com/contact/">Contact Us</a></div>
</div>
</div>
</div>
</div>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://static.dmcinfo.com/blog/41208/building-a-dba-dashboard-with-react-and-next-js-part-1/">Starting a DBA Dashboard with Next.js 16 and React: Dev Diary #1</a> appeared first on <a href="https://static.dmcinfo.com/">DMC, Inc.</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
