Separate theme definition in "frontity.settings.js"

Description

In frontity themes are structurally the same than any other package. But treating them at the same level has some problems to start understanding how Frontity work:

  • Themes are a special type of packages (the most important one?) because no frontity project has sense without a theme
  • For wordpress developers a theme and plugins (packages) are separated concepts and easier to understand
  • With the current way of defining a frontity project through frontity.settings.js you have to understand to start working with a theme
    • Namespaces (a namespace is asked when create-package and in frontity.seetings.js you see things such as state.theme.someThing
    • Packages
    • Packages are organized though namespaces

Examples

Possible solution

We think it would make sense to separate the definition of a theme in a frontity project to make it easuer to understand . Something like…

 "theme": {
    "name": "@frontity/twenty-twenty-theme",
    "state": {
        "featured": {
          "showOnList": true,
          "showOnPost": false
        }
    },
    "actions": {

    }
  },

In this way:

  • It would be easier to detect and understand the concept of theme in a frontity project
  • You won’t have to especify any namespace (this is important because the concept of namespaces won’t be necesary to be explained for introducing Frontity)

Also it would be easier to understand and explain themes (only state and actions would be relevant)

The final frontity.settings.js could be something like this one…

const settings = {
  "name": "webdevstudios-demo",
  "state": {
    "frontity": {
      "url": "https://test.frontity.org",
      "title": "Test Frontity Blog",
      "description": "WordPress installation for Frontity development"
    }
  },
  "theme": {
    "name": "@frontity/twenty-twenty-theme",
    "state": {
        "featured": {
          "showOnList": true,
          "showOnPost": false
        }
    },
    "actions": {

    }
  },
  "packages": [
    {
      "name": "@frontity/wp-source",
      "state": {
        "source": {
          "api": "https://test.frontity.org/wp-json"
        }
      }
    },
    {
      "name": "@frontity/menu",
      "state": {
        "menu": [
          [
            "Home",
            "/"
          ],
          [
            "Nature",
            "/category/nature/"
          ],
          [
            "Travel",
            "/category/travel/"
          ],
          [
            "Japan",
            "/tag/japan/"
          ],
          [
            "About Us",
            "/about-us/"
          ]
        ]
      }
    },
    "@frontity/tiny-router",
    "@frontity/html2react"
  ]
};

export default settings;

Thanks for suggesting this @juanma, I think it’s an interesting debate to have :slightly_smiling_face:

I’ll move it to the Framework Design category as I think it’s not a feature but a discussion we have to have about how this specific part is designed. I’ll give my opinion here but I think it’s also interesting that the @dev-team share their opinion as well, as it’d impact the framework in a way I don’t fully understand, and I think it’s something they also thought about in the past.

I think that during the design of the framework, we considered the option of separating the theme and the rest of the packages, but at the end we decided to treat them equally because they are just packages at the end. We talked a bit about this in this thread.

Not sure if we should consider themes special or the most important packages, as they are treated as any other package. In a Frontity project you always need, at least, three packages: one for the source, one for the router, and one for the theme. By default, when you create a new Frontity project you get:

  • @frontity/wp-source for the source.
  • @frontity/tiny-router for the router.
  • @frontity/mars-theme, or the theme you select, for the theme.

This are the default ones, but users could change them if they want. It’s true that users will usually just want to modify the theme, and that’s the reason why it’s included as a local package instead of inside node_modules.

I agree with this, as a WordPress user it’s easier to differentiate between theme and plugins, because they are actually different in WordPress. I’m not sure if this is as common in the React side. As far as I know, differentiating between themes and packages is not that common in React, but you all know more about this than me, I haven’t worked that much with other frameworks.

You’ll have more information here than me, as you’re more in contact with the community questions, but I don’t think users have to understand namespaces to start working with Frontity. As well as we’re defining the @frontity/wp-source settings (the api for example) without explaining the namespace source, I feel it’s the same with the theme. I feel you just have to understand the namespaces if you want to go deeper.

I’d love to understand better why you consider users have to understand namespaces to start using Frontity, maybe there are other things needed for this.

Anyway, as I said I think the @dev-team opinion would be really interesting here.

:one: When you want to create a theme from scratch you do something like this

>  npx frontity create-package cool-theme
? Enter the namespace of the package: theme
...

The first question you’re asked is Enter the namespace of the package so you need to understand what namespaces are in Frontity and why it’s important setting this here

:two: Also, when you start working with Frontity you get a frontity.settings.js as the configuration file for your project

const settings = {
  "name": "processor-blockquote",
  "state": {
    "frontity": {
      "url": "https://test.frontity.org",
      "title": "Test Frontity Blog",
      "description": "WordPress installation for Frontity development"
    }
  },
  "packages": [
    {
      "name": "@frontity/mars-theme",
      "state": {
        "theme": {
          "menu": [...],
          "featured": {
            "showOnList": false,
            "showOnPost": false
          }
        }
      }
    },
    {
      "name": "@frontity/wp-source",
      "state": {
        "source": {
          "api": "https://test.frontity.org/wp-json"
        }
      }
    },
    "@frontity/tiny-router",
    "@frontity/html2react"
  ]
};

export default settings;

To understand the logic behind this structure you have to understand that

  • Frontity projects are built over packages
  • Your theme is a package
  • There’s a thing called state that is used by packages to store data
  • state is organized through Namespaces assigned to each package

I think that understanding properly this file (why it is structured in this way and what’s the meaning of each part) is one of first steps to have a good Learning Experience in Frontity. And in the way it’s displayed right now, this includes understanding packages and namespaces,

I’ve always had mixed feelings about separating theme from the rest of the packages. We thought quite a lot about this when we started with the open-sourced version, so the decisions we made back then had strong reasons :slightly_smiling_face:


I think it’s important to understand that the Frontity framework, by design:

  • Delegates all functionalities to the packages
  • Tries not to apply any constraints to the packages

The Frontity framework is a mere “package aggregator”.

This design pattern has many advantages. It means that the framework is extremely versatile while being really simple/slim at the same time, with no preconceptions of the type of application/functionalities that run on top of it.

It also has some disadvantages, because we need to push all the functionalities to the packages and keep the framework “stupid” :smile:. That is sometimes more challenging and sometimes more inconvenient but, in the end, the advantages of this design pattern outweigh the disadvantages. I’m really pleased with the results of this decision so far. So I would like to maintain it as long as I lead the project.

For example, if you take a deep look, you can see that the Frontity framework has nothing to do with WordPress at all. All the WordPress functionalities belong to the packages.

Another great example of this is our upcoming @frontity/amp package because it’s going to be… well, a package. In the previous version, it was hardcoded in the core.

The advantage of pushing this type of functionalities to the packages is that the framework only needs to expose the APIs the packages need to implement their functionalities, without having a strong opinion about those final functionalities. Packages can be modified, so people can create an alternative AMP package if they want (maybe better than ours), avoid including the code of that functionality if they don’t use it by simply not adding the package, or even create similar packages, like a package to render PDFs, which hooks into the same framework APIs than the AMP package.

For this reason, I think it’s important to differentiate between the packages and the framework. Themes, sources, routers… are all packages. They do not belong strictly speaking to the Frontity framework, which only knows about a thing called “package” and doesn’t care what functionalities they implement.

In that regard, namespaces don’t even exist in the framework. They are mere conventions between packages, about how they organize their state, actions and libraries, so they can communicate and interact with each other. This is also by design.


About making themes a special type of package:

These are the reasons that lead us to not making themes a special type of package in Frontity:

  • The framework knows nothing about namespaces :man_shrugging:
  • A single site can have more than one package that acts as a theme.
  • A package can implement more than one namespace, for example, both theme and share at the same time.

The only solution I see that would avoid those problems without making the framework aware of namespaces and constrained about how a "theme" packages should work, would be to add a "themes" field in the frontity.settings.js file which would be an exact alias of the "packages" field. But I think that would be really confusing.


About removing the namespace of theme for themes, like this:

const settings = {
  theme: {
    name: "@frontity/twenty-twenty-theme",
    state: {
      featured: {
        showOnList: true,
        showOnPost: false,
      },
    },
    actions: {},
  },
};

I also thought about that when we designed the first version of the framework. We discarded it because:

  • It would be terribly confusing to define

    state.featured.showOnList;
    

    on the frontity.settings.js file, but then have to use

    state.theme.featured.showOnList;
    

    in the code.

  • It will break TypeScript support, because for TypeScript state.featured.showOnList is not valid.


About learning namespaces:

I understand your concerns, but I guess it’s going to be a necessary step in the learning process. They are an important part of using/design packages. Maybe it shouldn’t be the first thing to learn, but at some point, you need to learn about this convention.

To be honest, I don’t see a way to avoid that.


I feel like you’re going through the same thought process I went when I designed this and probably asking yourself the same questions I asked myself back then :smile::smile:

It’s not that I want to discourage you from giving your feedback, on the contrary. Please keep it coming :slightly_smiling_face:

3 Likes

Ok, I think I’m starting to see the whole picture.
Regarding data, Frontity framework just create the ground for the packages to communicate between them.

So, Frontity core is just responsible of creating the global object frontity and the 4 properties that will contain the 4 pilars of data managed by the framework

  • state
  • actions
  • root
  • libraries

Having this, namespaces is just a convention used by the packages to organize information in any of these places

Is there any place where it’s explained the responsibilities of each piece of the framework? I guess this is something you’ll explaing in the design principles document you’re preparing

I agree on this. It’s strange to define things like theme.state.featured.showOnList and then access this info like state.theme.featured.showOnList;

The current structure is more aligned with the final use


So, yes. You convinced me :blush:
Thanks a lot for the explanations

I see now that taking the definition of theme apart is not a good solution as it will introduce some other problems and it will kind of break the whole idea of packages

I think that these clear ideas can be (and should be explained) when introducing Frontity because this will not only make understand everything you’ll use in a Frontity project better (frontity.settings.js, use of state, … ) but also will make people understand the real potential of the framework (there can be a package for anything)

This is related to the Learning Curriculum but I think, there are some clear ideas to be explained in any introduction to Frontity

Basic architecture of hardware

WP server that connects via REST API to a NodeJs server that render the HTML using a React app as a source

Basic architecture of software

Frontity framework handle some things for you, like SSR, and sets the ground (state, actions, root, libraries) so packages can organize their data there around namespaces which simplifies extensibility and communication between them

Besides this, I think there are still some other things we could do to ease the life of Frontity developers:

Awesome. I’m glad this made sense to you :slightly_smiling_face:

That’s exactly what it is. Well put!


I agree we’re going to explain all this at some point.