Understanding Mars Theme
Guide to understand how our starter theme works.
Mars theme is our starter theme and is installed by default on frontity create
. Here we'll explain how @frontity/mars-theme
works.
If you yet don't understand the structure of a Frontity project, please read our guide Understanding a Frontity project.
Have a look at this Frontity Talk where we talk about the mars-theme
:
Frontity Utilities
Utilities are those libraries that are part of the Frontity core and need to be exposed to us in order to successfully develop a theme that integrates completely with Frontity. All those utilities are exposed in thefrontity
package.
For example, our state manager @frontity/connect
exposes a utility called connect
to wrap our React components so we can access the Frontity store from them. To avoid us the need to remember lots of packages and dependencies, we can import connect
and other libraries like this:
As you can see in the example above, we are accessing also styled
from frontity
. In this case frontity
is just exposing the API of @emotion/styled
, and it does this with other libraries like react-helmet
, so you get everything that you'd usually need in just one line.
Exports
The extension itself can be an object or a function that returns that object. You can see the object structure explained in the following code, along with what we are exporting in mars-theme
:
In each part of the exported object, what the extension defines needs to be inside its namespace
. In our case, all the things we are defining are inside the theme
namespace, but if our theme implemented, for example, a comments solution, that state, actions, etc., should be defined inside the comments
namespace. So, in the case of roots
, it would be something like:
Building the theme
There are some steps that we need to go through in order to have our theme working:
SSR populated
First of all, we want our server-side rendering to be equal to our client-side rendering to not harm the UX and SEO. In order to do this, we are going to use an action called beforeSSR
. This action will be run by @frontity/core
before the server-side render is generated by React and it's the best place to request the data we need from our WP:
We are doing this in our src/index.js
file:
Now that we have the data we need to render our app, we can start writing some React. All the components described below can be found inside src/components
.
Theme component
Our main React component will be Theme
, where we are deciding what kind of view to render, and in order for that component to access the store, we need to wrap it with the connect
function. Once it's wrapped, we can access state
and actions
directly from the props. In this case, we are using state.source.get()
to retrieve info about what kind of content should be rendered in the current path. If it happens to be an archive, we will render the <List />
component, if a post type, the <Post />
and if for some reason wp-source
couldn't retrieve the data from our WP, we will render a 404 page.
Here you have the code of Theme
with some comments:
Between the Post
component and the List
component there are a bunch of different things going on here. I'll start with List
.
List component
It is exported from list/index.js
. There, we are using loadable
from frontity
(which is actually an alias for the default
export of @loadable/components
) to split the code of our List
component, so it won't be loaded if a user access directly to a Post
view, and instead the code will be requested when the user clicks on a list view. This is helpful to reduce the loading times and times to interactive of our site. The less code we have, the less time the browser spends evaluating it.
Now, our List
component is the responsible to render a list of posts, and for that it needs to know what posts to render. We are using state.source.get(link)
and its items
field.
The last detail we are going to explain is how we are doing pagination on List
.
We are getting the total of pages for that list from state.source.get(link)
and we are checking if we are either in the first one, the last one, or in the middle. Using the React hook useEffect
we are prefetching the next page when the component mounts, so in the case the user goes there, he doesn't have to wait for the response from the WP REST API.
Depending on the page we are at the moment, we render different links to travel through the list. For that we are using our own Link
component, which accepts the same parameters as actions.source.fetch()
or actions.router.set()
.
Post component
There is something new here, that we haven't done on List
. We are doing a preload of the List
component (as it is a dynamic component and we don't have that code yet). Once we have our site rendered and working, we preload the code for List
, so the user won't need to wait for it later if she decides to visit a list of posts.
Defining the theme state
The last thing that might need to be explained is how we define state
for our extension in order to use it within React and be able to set it with a frontity.settings
file in a Frontity project.
In mars-theme
we are defining the following state
:
And we are using it as shown below:
And when we create a new Frontity project where our theme is installed, that state can be changed in frontity.settings.js
:
Still have questions? Ask the community! We are here to help ๐
Last updated