ThemeBuilder + Next.js is a great approach for new React app development—especially now that KendoReact is rolling out new Server Components with RSC architecture, which will be right at home in Next.js!
With the publication of the updated React docs last year, the use of frameworks—with Next.js at the top of the list—is the official recommendation of the React team when it comes to getting a new project up and going.
I hadn’t had a chance to explore Next.js in much detail, so I decided to knock out two birds with one stone—rework my personal website (always on a developer’s to-do list, right?) and get up-to-speed with this new suggested approach for React projects. Of course, I also leveraged the Progress KendoReact library and ThemeBuilder for my components and styling, because—why not? Quick, easy, accessible: what’s not to love?
The Next.js ecosystem really favors CSS modules, with built-in support simply by including the module.css
extension in your file names. They also have built-in support for Sass, after a quick npm install
. Since I wanted to check out the “standard” Next.js experience, I went ahead and followed their recommendations, making use of both. Then, I installed my KendoReact components and set up my license.
Since I was just working on my personal website (not a super-complex, full-featured application), I didn’t really need a proper design system—I just made a couple quick tweaks to the typography and color scheme of the Kendo Default theme in the ThemeBuilder and called it good!
I knew I wanted my site to make use of the prefers-color-scheme
media query, so it would be able to swap automatically between light and dark mode to match the user’s system settings. However, because my design was so simple, I didn’t bother creating two entirely different themes for this—I didn’t want to mess with switching between stylesheets just to swap a couple hex codes.
Instead, I added extra custom variables to my ThemeBuilder project: dark-mode variables for body background, component background, text color and accessibility-adjusted versions of my two main colors (to ensure I always had high enough color contrast). So, in total, five extra custom variables got exported to my _tokens.scss
file along with the standard ones for the Default theme.
ThemeBuilder offers exports in vanilla CSS, as well as Sass; in this case, I already knew I wanted to use the Sass ones. That meant that the first thing I needed to sort out was where to place my ThemeBuilder-exported Sass files. In Next.js, that required adding global styles, in addition to the default CSS module scoped styles.
Because I was using the most recent stable version of Next.js (14.0, when this blog was written), that meant that the App Router was the default structure—as opposed to the Pages Router used in Next.js 13.3 and earlier. As it turns out, this makes a slight difference when it comes to where your global styles will live. I’ll cover both ways—how I did it in the current Next.js version using App Router, and how you might need to configure things for a legacy application using the Page Router.
If you’re using this more recent approach, then global styles can be imported into any layout, page or component within the app
directory. For clarity and easy searchability, I renamed my ThemeBuilder-exported index.scss
file to global.scss
. Then, I imported it into the root layout file—app/layout.tsx
(or app/layout.js
, if you’re not using TypeScript).
If you’re using this older approach, you’ll need to create a new file called _app.js
within the pages
directory and include this code:
import '../styles/global.scss';
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Then, restart your dev server and you should be good to go! Just remember, this file is the only place where global styles can be imported using the Pages Router!
Since I knew I wanted a super simple dark mode (as mentioned before) I made a short addition to the end of my global.scss
file to include the prefers-color-scheme
media query. There, I used the custom variables I created in ThemeBuilder, imported from the _tokens.scss
file, to redefine a couple key styles. In my actual project, there were a few more than this, but you get the idea.
@media (prefers-color-scheme: dark) {
body {
background-color: $tb-kendo-body-bg-dark;
}
a {
color: $tb-kendo-accessible-link-text;
}
}
If I’m completely honest, sometimes I struggle to write blogs like these because it feels like there’s not much to say—everything just works! In this case, when I first started the project, I was a little nervous about how easily the exported ThemeBuilder stylesheets would work with the Next.js structure. I had heard from other developers that Next.js was highly opinionated, and I had a little hesitation about how much adjustment might be required for these two technologies to work and play well together.
My conclusion is this: While it’s true that Next.js is opinionated, they also built in solutions for the main situations where developers were most likely to need something outside the default configuration. Next.js doesn’t include global style support out of the box, so you can’t literally drag and drop the ThemeBuilder files into the app folder—the way you can with a CRA app. However, getting global styles set up in Next.js was well-documented and not terribly challenging. Once that was in place, we were pretty much back into the drag-and-drop zone when it came to implementation.
This will almost certainly be my approach for new app development moving forward—especially now that KendoReact is rolling out new Server Components with RSC architecture, which will be right at home in Next.js! And, of course, if you aren’t already using KendoReact, you can try it out—in combination with your framework of choice—completely free for 30 days.
Kathryn Grayson Nanz is a developer advocate at Progress with a passion for React, UI and design and sharing with the community. She started her career as a graphic designer and was told by her Creative Director to never let anyone find out she could code because she’d be stuck doing it forever. She ignored his warning and has never been happier. You can find her writing, blogging, streaming and tweeting about React, design, UI and more. You can find her at @kathryngrayson on Twitter.