Defining default settings for Frontity packages

Roadmap Card

Description

We need some default settings for a Frontity package for two scenarios:

  • When we add the package using npx frontity create.
  • When we add the package using npx frontity install-package (in the future).

Right now, the settings of mars-theme are hardcoded but that obviously doesn’t scale.

User Stories

As a Frontity package developer
I want to expose my desired default settings somewhere
so that when other devs install my package, they start with those settings in their frontity.settings.js file

Possible solution

We could get the settings from the package itself after installing, something like this:

installPackage("@frontity/mars-theme");
const pkg = require("@frontity/mars-theme");
const settings = pkg.state;

but that won’t be ideal because:

  1. It won’t include arrays, which are not populated in the internal state:
      state: {
        theme: {
          menu: []
        }
      }

versus

      state: {
        theme: {
          menu: [
            ["Home", "/"],
            ["Nature", "/category/nature/"],
            ["Travel", "/category/travel/"],
            ["Japan", "/tag/japan/"],
            ["About Us", "/about-us/"]
          ]
        }
      }
  1. It will include parts that are not meant to be settings. For example, the twentytwenty-theme has things like isMobileMenuOpen: false or isSearchModalOpen: false in the state.

My proposal is that we use the frontity.config.js file for that:

// frontity.config.js
export const defaultState = {
        theme: {
          menu: [
            ["Home", "/"],
            ["Nature", "/category/nature/"],
            ["Travel", "/category/travel/"],
            ["Japan", "/tag/japan/"],
            ["About Us", "/about-us/"]
          ],
          featured: {
            showOnList: true,
            showOnPost: true
          }
        }
      }

The frontity.config.js file is meant to be used for other configurations that live outside of webpack, for example babel or webpack because it won’t be affected by the entryPoints, so I think it’s a good place to store this.

Obviously, it can be optional.

It will be something like this:

installPackage("@frontity/mars-theme");
const { defaultState } = require("@frontity/mars-theme/frontity.config");

If it exists, we add it along with the name of the package:

// frontity.settings.js generated
  packages: [
    {
      name: "@frontity/mars-theme",
      state: {
       theme: { /* desired default settings... */ }
      }
    }
  ]

If it doesn’t exist, we just add the name:

// frontity.settings.js generated
  packages: [
    "@frontity/mars-theme"
  ]

I think the general idea sounds fine to me :slight_smile: Just a few points were not entirely clear:

  1. I think you meant “create a project” here, right?
  1. Where is this frontity.config.js supposed to be located? Is the idea that is it will be part of a theme (for example it would be located in packages/mars-theme/frontity.config.js) and published on npm together with theme? And then the create command would read the contents of this file when we create a new project?

  2. I don’t quite understand what you were trying to say here:

  1. It’s not clear to me actually why we do the following:

In the @frontity/mars-theme, we put the following in the state in the top-level index.js:

state: {
    theme: {
      menu: [],
      isMobileMenuOpen: false,
      featured: {
        showOnList: false,
        showOnPost: false
      }
    }
  },

But then, when we actually “use” the theme, for example in mars-theme-example, we add some additional configuration for the menu, etc. in the frontity.settings.js like:

packages: [
    {
      name: "@frontity/mars-theme",
      state: {
        theme: {
          menu: [
            ["Home", "/"],
            ["Nature", "/category/nature/"],
            ["Travel", "/category/travel/"],
            ["Japan", "/tag/japan/"],
            ["About Us", "/about-us/"]
          ],
          featured: {
            showOnList: true,
            showOnPost: true
          }
        }
      }
    },

Why can’t the theme come with those settings by default and then we would not have to copy them into the frontity.settings.js file?

Yes.

In the root. Yes. And yes.

We already have plans to use the frontity.config.js file for other things, like for example when a package wants to extend babel or webpack.

Yes, it works that way: if you remove some settings from your frontity.settings.js file then the default setting (the one included in the src/index.js file) is used. We thought that having your frontity.settings.js file populated with some settings would be more useful and intuitive to start learning what you can do with a package than having an empty file. But we are not adding all the settings, only some of them. People can always explore the settings of a package in the documentation. WpSource is a good example: https://docs.frontity.org/api-reference-1/wordpress-source#settings. Apart from that, we can add some settings for the frontity.settings.js file that are tied to the initial project (pointing to test.frontity.io for example) that I don’t think it would make sense to have as a default because if you delete a settings that is required from your frontity.settings.js file the package should throw an error or a warning, not go back to some default pointing to test.frontity.io (I know we are not doing that for state.source.api but we should). And finally, when we merge the state, we had to choose between substituting arrays and merging arrays. We choose merging arrays because it is much more useful for most scenarios, but it means that the arrays of the default state (the one of src/index.js) must be empty.