Gia Thinh Nguyen
Published on
While building this blog, I found the combination of Next.js and Theme-UI to be absolutely amazing with the former providing a top-of-the-class routing solution and the latter bringing consistency and a source of truth to your CSS by creating an interface to your code and design system. If you are interested in giving this a go, then let's move on! Otherwise, feel free to grab the repo here.
Like any typical project, we start off with a create-next-app
command followed
by a few depedencies for enabling Typescript and linting.
Next.js will automatically fill in the tsconfig
with some defaults once you
run next dev
so now we can start writing some typescript starting with
replacing the current pages with our own _app.tsx
and _document.tsx
.
This is where we will introduce the ThemeProvider
from Theme-UI to our app,
additionally, Theme-UI uses emotion under
the hood, which currently provides Server side rendering (SSR) capabilities out
of the box with little to no configuration.
And of course, to actually render a page, we can start off with a simple
index.tsx
page.
Next.js relies on a file-routing based system which means you should name your pages according to the folder hierarchy. For more info see here
At this point, we are now set to install our Theme-UI library with the command
yarn add theme-ui
. Once installed, we will need to update our files to
interface with the API as well as add a theme.ts
file to hold all of our
design tokens, which are basically keys and values of CSS we would want to use.
The documentation provides a few themes in this demo
to get started. We'll pick my personal favorite, deep
!
You can know delete any css
files under the styles folder, and replace it with
your theme file.
We will take a look at what these tokens represent in later post, for now we have
our theme ready to be consumed. Similar to most CSS-in-JS solutions, Theme-UI
comes with a ThemeProvider
context that will inject our tokens where they are
needed. We can do so by tweaking our _app.tsx
file like so.
Next, we will need to add a script to avoid one of the modern web's biggest annoyances, the dreaded Flash of Incorrect Theme caused by server side rehydration of markup. This is a pretty big issue if you want a painless dark mode experience, and fortunately Theme-UI solves that problem in a typical one-liner fashion. Alot of great minds have put together their thoughts on this, which I'll share at the end, but for now simply add this line. Even though our theme hasn't been setup for a Dark mode, it can be done so at a later time without too much hassle.
And there you have it, Theme-UI is now fully integrated to your Next.js project, ready to build beautifully themed components.
Before jumping into building UI components, it's always a best practice to be familiar with the API you will interacting with. Luckily, the folks behind Theme-UI sought out to create the best developper experience possible, especially when it comes to code hygiene which is achieved through typescript support and practical utility functions for styling components on the fly.
I'd love to share my tips and tricks in another tutorial, but this short and sweet documentation should be enough to get started. I hope to write posts about some of the UI components I've built for my blog.
This concludes most of the tutorial, you can check out the repo on my github. The following contains a few goodies I've found useful when working with this setup.
Every good project should start with a CSS global styles 🌎. This can be done in
a number of ways, but since Theme-UI comes with emotion
we can make use of its
<Global/>
component to create our own CSS reset.
Importing this into our _app.tsx
file will do just the trick!
If we are truly striving for the best DX (Developer eXperience), then we definitely
need some linting going on! One of my favourite ways of doing this is actually with
a few extra lines in the package.json
file. As of Next.js 11,
the framework now comes with ESLint support in by way of a library. Next.js is
a fairly opinionated framework with stricter rules surrounding certain use-cases.
It previously relied on a bunch of eslint packages to do that work. Now we only
need a single package 🔥.
This is particularly helpful when working with Next.js for the first time as the
linting will highlight specific Next.js only optimizations that are recommended
(try adding an <img/>
tag in your index.tsx
page to see in it action).