home

Add Theme-ui to Next

How to add theme-ui to NEXTjs

Today i decided to finally take the plunge and start learning NEXTjs. I've been working with Gatsby for two over years now, have created many sites and themes and generally feel very comfortable in that environment. But it was time, finally to bite the bullet and see what all the fuss was about!

When i build Gatsby sites i always style them with theme-ui. Its my favorite way to style websites as it allows you to globally control your sites styles from one file, lets you work responsively using simple array syntax and works wonderfully well with Gatsby. I was curious though, how would it play with NEXTjs? Would the setup be as simple as with Gatsby? After all, and i quote the corgi master himself Chris Biscardi "Theme-ui is just a set of react context providers and a pragma". How hard could it be?

Well it turns out not very hard, once you have figured it out that is.

I started with the starter tutorial on the NEXTjs website and got things up and running in no time. Its very impressive NEXTjs, though i haven't dived too deep into it yet. But i digress, when we add theme-ui to our website we generally want to wrap our root element or page with it's context. The only problem was, when i spun up the NEXTjs tutorial example, there was no root element, no app.js. Only a pages folder, some components and a public folder.😕

The answer turned out to be overriding the base app.js file and providing the context that way. Lets dive into some code..

Install theme-ui

GNU Bash icon
yarn add theme-ui

Create our theme file

Create a new folder called components and a file named theme.js

GNU Bash icon
mkdir -p components/theme.js

We are just going to test if it works by changing the color of some text so no need to add any more than some colors for now.

JavaScript icon
export default {
colors: {
text: '#FFFfff',
background: '#121212',
primary: '#000010',
secondary: '#E7E7E9',
accent: '#4CEA22',
},
};

Overriding the base app.js

Create a new file inside of pages and name it _app.js

GNU Bash icon
cd pages && touch _app.js
React icon
import React from 'react';
import { ThemeProvider } from 'theme-ui';
import theme from '../components/theme';
const App = ({ Component, pageProps }) => {
return (
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
);
};
export default App;

The docs explain this very well so i will quote them here:

The Component prop is the active page, so whenever you navigate between routes, Component will change to the new page. Therefore, any props you send to Component will be received by the page.

Lets try out our new colors! Open the index.js file located in the pages folder and use the sx prop and add a p tag.

React icon
import Head from 'next/head'
import Link from 'next/link';
export default function Home() {
return (
<div className="container">
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1 className="title">
Read <Link href="/posts/first-post"><a >First Post Page!</a></Link>
</h1>
<p sx={{
fontSize: '6em',
cursor: 'pointer',
":hover": {
color: 'accent'
}
}}>TEST</p>
/* lots and lots of other stuff..... */
</div>
</main>
</div>
)
}

Now if we run yarn dev we should see the magic happen....

Wait..

Nothing happened! 🥺

Thats because we forgot to add the jsx pragma! I spent an hour trying to figure out why it wasn't working and that was the reason.

React icon
/** @jsx jsx */
import { jsx } from 'theme-ui'
import Head from 'next/head'
import Link from 'next/link';
export default function Home() {
return (
<div className="container">
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1 className="title">
Read <Link href="/posts/first-post"><a >First Post Page!</a></Link>
</h1>
<p sx={{
fontSize: '6em',
cursor: 'pointer',
":hover": {
color: 'accent'
}
}}>TEST</p>
/* lots and lots of other stuff..... */
</div>
</main>
</div>
)
}

You're welcome 😘