Frontity Building Blocks

Note: This is part of my Learning Frontity series. This learning post is still in active development and updated regularly.

In my recent CSS-Tricks article Mars Theme: A Deep Look at Frontity’s Headless WordPress Theme, I briefly described Frontity building blocks. However, during its editorial process some portion of background information was left out.

In the article, a very brief (one para) description of @frontity/package or “Frontity building blocks” without more detail explanation was provided. An additional supplimental overview information on the @frontity/package components with code syntax and use cases that are more relevant for understanding Frontity Mars theme is described below. Further more detailed information can be found in this package reference API.

Fronty’s state

Frontity has its own react-easy-state based state manger called “frontity connect”, which is similar to useConnect React hooks. The frontity.settings and project data are stored in in its state. In the frontity doc, the @frontity/connect is described as follows:

Frontity connect is a higher order component that takes a React component as an argument. It passes the Frontity object to the React component specified in the argument via props. The Frontity object has amongst its properties state, actions and libraries. connect therefore enables a component in our theme to access data stored in the state, or functions available in actions“.

As discussed earlier, frontity state can be modified in frontity.settings.js file. The following example from mars-theme package:

//src/html/index.js
const marsTheme = {
  ...,
  state: {
    theme: {
      // This field will be used in our Nav bar.
      // Here we are defining the default value.
      menu: [],
      featured: {
        showOnList: false,
        showOnPost: false
      }
    }
  }
};

In the example above, we defined our menu items under state.theme. menu, which is now available for later use in our nav.js file.

// src/components/nav.js
const Nav = ({ state }) => (
  <>
    {state.theme.menu.map(([name, link]) => (
      // ...
     // ...
    ))}
  </>
);

export default connect(Nav);

This understanding of frontity state doc describes frontity state in more detail with use case examples.

Frontity ‘actions’

Frontity actions are frontity’s reusable functions that are essential to expose other frontity packages. They modify frontity state but don’t return anything. It is described as similar to derived state which receive ({ sate }) in their argument but gets stripped out while consuming.

One of the use case example of actions described in the doc is, its use in tiny-router utility package where it exposes actions.router.links which then modifies state.router.link thus making sure it’s in sync with URL of our browser. Some examples of actions triggered by frontity actions include: beforeSSR, afterSSR etc. with an example from frontity doc below:

//from mars-theme
const marsTheme = {
  name: "@frontity/mars-theme",
  roots: { ... },
  state: { ... },
  actions: {
    theme: {
      beforeSSR: async ({ state, actions }) => {
      // We fetch the initial link.
        await actions.source.fetch(state.router.link);
      // NOTE: This is not needed if autoFetch is activated in your router.
      }
    }
  }
};

The @frontity/core runs the beforeSSR action before the server-side render is generated and data fetch request from the wordpress endpoint.

Frontity Libraries

Similar to actions functions, libraries are sets of reusable tools (e.g., html2react) which are by their own packages or by other packages. For example, in the mars-theme root component, its libraries include html2react array processor tools to process image, iframe, links. Any additional can be included here (eg., blockquotes, …).

Following is an example of how libraries are used in frontity theme:

// packages/mars-theme/src/components/index.js
//from mars-theme
// ...
import customProcessor from "./processors/custom";
// ...
const marsTheme = {
  name: "@frontity/mars-theme",
  roots: { ... },
  state: { ... },
  actions: { ... },
  libraries: {
    html2react: {
     // use html2react to process the <img>, <iframe>, <link> tags 
     // inside the content HTML.     
      	processors: [image, iframe, link, customProcessor],
     },
   },
};

Any custom processors can be directly added to the libraries.html2react.processors too. First we have to import our customProcessor (line 4) and then add to the libraries (line 15).

Frontity Head

Frontity head is a React component available via frontity-core package which injects HTML <head> tag using react-helmet which allows to add title, meta tags, scripts, make other changes. The following code snippets shows how head is used in frontity mars-theme. It’s use case example is described in frontity package API reference doc.

//package/mars-theme/src/components/index.js
import { Head } from "frontity";
// ...
{/* Add some metatags to the <head> of the HTML. */}
      <Title />
      <Head>
        <meta name="description" content={state.frontity.description} />
        <html lang="en" />
      </Head>
// ...
// ...
;
Frontity Switch

The @frontity/components/switch component is an alternative to JavaScript switch statement logic and ” the first child component that returns true as the value of its when prop .. the last child component should not have a when prop will be rendered if no other component matches the condition“.

A use case example of switch taken from the frontity mars-theme is shown below. Other use case examples of switch are described here.

//package/mars-theme/src/components/index.js
// ...
import Switch from "@frontity/components/switch";
// ...
const Theme = ({ state }) => {
  const data = state.source.get(state.router.link);
// ...
  return (
   // renders a different component depending on the type of URL we are in.
    <Switch>
      <Loading when={data.isFetching} />
      <List when={data.isArchive} />
      <Post when={data.isPostType} />
      <ErrorPage /> {/* rendered by default */}
    </Switch>
  );
 //...
};
Frontity Link

The @frontity/components/link component is used to define links that works with the internal routing system. This Link component uses the actions.router.set(link) method from @frontity/tiny-router and creates an <a/> tag.

// @frontity/components/link package
import Link from "@frontity/components/link";

const MyComponent = () => (
  <Link link={linkUrl} onClick={(e) => console.log(e)}>
    This is a link
  </Link>
);

It requires state.source.url props from WordPress data source the URL to link to properly. Any unknown props passed to the link are passed down to an anchor </a> tag

Putting the building blocks together

How frontity framework puts these building blocks, packages, and utilities tool together is explained in this frontity doc. “When starting frontity, all the packages defined in frontity.settings.js are imported by @frontity/file-settings and the settings and exports from each package are merged by @frontity/core into a single store where you can access the state and actions of the different packages during development using @frontity/connect, the frontity state manager.

In the following section we will familiarize our-self how these building blocks, utilities and exports are put into practice in @frontity/mars-theme package to create a functioning headless Frontity site with WordPress endpoint.

Please note that this is only supplemental information on Mars Theme: A Deep Look at Frontity’s Headless WordPress Theme article which was recently published in CSS-Tricks.

Useful References

The following is list of references link that I gathered during my brief research. While preparing this post, I have also referred some of the following references extensively. Please to refer original posts for more detailed information.