The marketing pages will be our first theme. All themes after this will build on top of the foundation we create here.
Instructor: [0:00] Our first theme will be Gatsby theme marketing. These are the pages that our marketing team will control whether through contracts or their own work. By putting these files into a separate theme, we can enable the marketing team to have autonomy over the pages they control.
[0:12] The relevant pages are the home page, which we're on now, the pricing page and the company page. First create a folder for the Gatsby theme marketing package. This will be a folder called Gatsby theme marketing inside of the packages folder that we created. We can go into that folder using cd and initialize a new package.json.
[0:38] Note that the dash Y flag skips all of the questions, but you can answer the questions if you want to. My package.json looks like this. We're going to move three pages into our theme, company, index, and pricing.
[0:51] To do that, we need to create the source and pages directory. Now we can take our files and move them into our theme. Remember to remove these files from the original site, as if they're in the original site, they will override the ones in your theme.
[1:14] Next, in WWWs package.json, we are going to add Gatsby theme marketing as a dependency. In the Gatsby config for WWW, we also have to add Gatsby theme marketing. Now that both files are saved, we can install our dependencies, which will link our package which is the Gatsby theme into our site WWW. Now we can run the site again.
[1:48] Now that we run into an error here where Gatsby can't find Gatsby theme marketing in the Gatsby config that we're using, even though we just added it. The problem here is that nodes require algorithm, requires either an index.js file or main declaration in the package.json.
[2:09] We can fix this issue by creating an empty index.js file in which I usually put a comment that says boop. That is more obvious that it's an intentionally empty file. The index.js file has to go in the root of our theme.
[2:22] Now we get further, but we see a new error. Can't resolve ../components text in source pages. In this case, we're looking at the company file, but the index file also uses it as you can see here. We'll copy the entire components folder into our theme.
[2:43] Note that we've copied the files and haven't moved them. This means we have a copy of the component in WWW or other pages that are using them, as well as a copy of the components folder in our theme, which we'll modify. Note that when we view our site now, nothing has changed, even though the new files are coming from our theme and not the site itself.
[3:04] If we look at some of the components, we can see that we depend directly on theme UI, Gatsby, React, and a couple other libraries. If we go to the theme's packages adjacent, we can add theses dependencies.
[3:16] This is important for anybody using our theme in the future, as if we don't specify the dependencies here, it won't install. Note that we have the opportunity here to specify Gatsby, React, and React DOM as pure dependencies.
[3:32] Since this is a Gatsby theme, it's guaranteed that Gatsby, React and React DOM will be installed already. Then, we can actually skip that, unless we have a reason to block certain version of Gatsby, React or React DOM.
[3:45] This is theme UI presets and we'll use this package to show how the files in our theme and the themes different from the files in our site, without either of them conflicting. In the root of our site, we'll run yarn to install our dependencies.
[4:01] Right now, if we look at the Gatsby SSR, Gatsby browser and wrapRootElement files, we see that we use a global theme provider, the provider tokens and MDX components to the entire site. This, currently, affects our theme and if we provided this in our theme, it would also affect the root site.
[4:20] We'll copy the Gatsby SSR, Gatsby browser and wrapRootElement files into our theme. Note that in our theme, if we allow our theme to insert global styles, this will conflict with the site that uses them. Then, we'll remove the global styles declaration, as well as the correspondent import.
[4:44] We'll also change the tokens preset and pass it in to our theme provider. This will make it more obvious that we're using the marketing theme to render these pages rather than the site itself, which uses the deep preset. Now, we can run the site again.
[5:00] After running the site, we refresh our page. We'll see that the colors for the navigation and our page changed but, also, all the colors in our blog, our dev blog and our swag site all changed as well.
[5:15] What's happening here? The problem of conflicting theme providers, conflicting React context or other global elements of your app, it's an easy trap to fall into when developing themes for general consumption.
[5:28] We have a solution now and that's using our own React Context for our theme. We'll add isolated theme UI to the dependencies list in Gatsby theme marketing. Then we'll create a new file and source called, "Context." This file imports a JSX pragma and an MDX pragma from the isolated theme UI package.
[5:54] If we look at our components, we can see that we're already using the JSX pragma from theme UI and we're about to replace that. We create our own React Context with theme and components keys and then we bootstrap our own pragmas using the functions from isolated theme UI and our own context.
[6:17] Because we're using our own context, nobody else we'll be able to conflict with the values that we set here without explicitly using our context to provide values. We'll also create a new file called, "Theme.js."
[6:29] In this file, we'll take the import of our theme UI preset from our wrapRootElement and export it as a default export. We move this file into source because this allows any consumer of our theme to shadow this as we'll see later. We've provided a default set of tokens that can be changed out by the user.
[6:49] We're now going to get rid of the theme provider from theme UI because we're going to use our own. We'll Import "my theme context" from the context file we just created as well as the theme from the token's file we just created.
[7:00] We will replace theme provider with my theme context.provider imported from our bootstrap context. We'll also set theme and components as their own keys and the values for the provider. Now that we've provided our tokens through own context, we can use them in our components.
[7:18] In header, we'll replace the JSX import with an import from Context. We'll do the same in the other components' files. Finally, we can re-introduce the global styles that we removed earlier from wrapRootElement into each of the pages that we'll be rendering from our theme.
[7:42] We'll need useContext from React as well as the global component from the motion core and my theme context from the theme context we bootstrapped earlier. Then we can use the use context hook to pull the theme out of our context and apply it using the global component. We'll want to do this in each of the other pages as well.
[8:02] Note that using the global component and page templates and pages that we control in our theme is OK because the global component we'll mount and unmount when those pages mount and amount. This means our global styles only affect pages that we control as opposed to pages that a user controls or another theme controls.
[8:23] Now that if we look at our site now, we can see that the home page, the pricing page and the company page have their own style while the blog page, the depth blog and the Swag store as well as our app all have the original site style.
[8:37] That's it. We've created a Gatsby-themed marketing that can be controlled completely by our marketing team. It comes with a default style and three pages. These pages can be extended by the team and when we integrate this back into our site, we can make sure it uses the token set that our site wants to use.
[8:56] To do this, we'll shadow the themes file we created earlier in WWW in source. We'll create a new file under Gatsby themed marketing, themed.js. In this file, we'll import the deep theme from theme UI presets and exported it as the default export.
[9:15] This file shadows the theme file in our theme and changes the tokens sets that the theme is going to use. If we rebuild the site, we can see that it changes the using the deep theme even though the token set that our theme uses is different than the token set that our site is using. We still have a unified experience across all of our pages.
[9:42] This allows us to install our theme into any site without worrying about breaking anything on that site and without worrying about that site breaking us. This is an important concept if you're going to create themes for public consumption.