Author: Richard Haines

Posted: 24 Apr 2020

take me there

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

1yarn add theme-ui

Create our theme file

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

1mkdir -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.

1export default {
2 colors: {
3 text: "#FFFfff",
4 background: "#121212",
5 primary: "#000010",
6 secondary: "#E7E7E9",
7 accent: "#4CEA22",
8 },
9};

Overriding the base app.js

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

1cd pages && touch _app.js
1import React from "react";
2import { ThemeProvider } from "theme-ui";
3import theme from "../components/theme";
4
5const App = ({ Component, pageProps }) => {
6 return (
7 <ThemeProvider theme={theme}>
8 <Component {...pageProps} />
9 </ThemeProvider>
10 );
11};
12
13export 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.

1import Head from 'next/head'
2import Link from 'next/link';
3
4export default function Home() {
5 return (
6 <div className="container">
7 <Head>
8 <title>Create Next App</title>
9 <link rel="icon" href="/favicon.ico" />
10 </Head>
11
12 <main>
13 <h1 className="title">
14 Read <Link href="/posts/first-post"><a >First Post Page!</a></Link>
15 </h1>
16
17 <p sx={{
18 fontSize: '6em',
19 cursor: 'pointer',
20 ":hover": {
21 color: 'accent'
22 }
23 }}>TEST</p>
24
25 /* lots and lots of other stuff..... */
26
27 </div>
28 </main>
29
30 </div>
31 )
32}

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.

1/** @jsx jsx */
2import { jsx } from 'theme-ui'
3import Head from 'next/head'
4import Link from 'next/link';
5
6export default function Home() {
7 return (
8 <div className="container">
9 <Head>
10 <title>Create Next App</title>
11 <link rel="icon" href="/favicon.ico" />
12 </Head>
13
14 <main>
15 <h1 className="title">
16 Read <Link href="/posts/first-post"><a >First Post Page!</a></Link>
17 </h1>
18
19 <p sx={{
20 fontSize: '6em',
21 cursor: 'pointer',
22 ":hover": {
23 color: 'accent'
24 }
25 }}>TEST</p>
26
27 /* lots and lots of other stuff..... */
28
29 </div>
30 </main>
31
32 </div>
33 )
34}

You're welcome 😘

Edit on GitHub.Previous: CSS grid responsive cardsNext: A Digital Garden