volto icon indicating copy to clipboard operation
volto copied to clipboard

Plone 7 frontend (Seven)

Open sneridagh opened this issue 10 months ago • 9 comments

PLIP (Plone Improvement Proposal)

Responsible Persons

Proposer: Víctor Fernández de Alba (@sneridagh)

Seconder: Timo Stollenwerk (@tisto)

Last Modification: March 2025

Abstract

Modernize Volto using the current standards and frameworks.

Motivation

Plone Volto frontend is (as per 2025) eight years old. We architectured and implemented Volto using the libraries, frameworks, resouces and best practices that were available back in the day. These have all changed, in the midst of the ever-changing and ever-evolving React ecosystem, therefore, the way of developing React applications nowadays have dramatically changed.

React 19 is stable now, settling (at last) a common paradigm for efficient data fetching in both the server and the client. Nowadays React frameworks leverage and are embracing this paradigm, battle testing them in production.

Plone has to embrace also these best practices an patterns, replacing all the legacy libraries and old patterns with the current ones.

We decided to use React Router 7 as framework of choice for the implementation of the Volto successor. See the rationale behind in the corresponding PLIP: https://github.com/plone/volto/issues/6324.

We have settled on the strategy explained in this PLIP, after working on the PoCs that we've investigated during the last months. I explained it thoroughly in https://github.com/plone/volto/issues/6320.

The summary is that if we were to implement the list of approved improvements, we would end up by rewritting the vast majority of what we know today as Volto, and the final outcome would be still a complete different beast. Volto is the sum of small pieces that put together make our beloved frontend in which we grew all these years. These fundamental and structural pieces are the ones that we sliced and made them work standalone in the last year. The idea is to grab these pieces that define Volto itself, and put them together in a new, modern and capable frontend app.

Taking @plone/registry as base, and using exactly the same add-on driven development approach and by using the same concepts, patterns and data structures, we plan to achieve the maximum compatibility with existing Volto sites, carefully designing the migration path from Plone 6 to Plone 7.

We think that crafting add-ons able to work in both Plone 6 and Plone 7 would be possible, even today with the existing PoCs.

These are the points of improvement for PLIPs for Plone 7:

  • Move to a modern bundler (Vite) (React Router 7 already is Vite-powered)
  • Use React Router 7 as framework - https://github.com/plone/volto/issues/6324
  • The CMSUI as a pluggable standalone app - https://github.com/plone/volto/issues/6325
  • Refactor the base components (both public UI and CMSUI) removing Semantic UI and using @plone/components - https://github.com/plone/volto/issues/4352
  • A new theming system (without Semantic UI) - https://github.com/plone/volto/issues/6322
  • A new unified block model for both public UI and CMSUI - https://github.com/plone/volto/issues/6316
  • Enhanced contents view - https://github.com/plone/volto/issues/4756
  • Use the new JS client package - https://github.com/plone/volto/issues/4347
  • Implement Quanta in the CMSUI - https://github.com/plone/volto/issues/4332

Assumptions

We have all the basic pieces identified that we will need on the table so we can start building up. These pieces are commanded and orchestrated by @plone/registry and are composed by the modular @plone/* packages. Some of these pieces will require to be improved and evolved, but basically, all "rocket science" level issues are sorted out.

Proposal & Implementation

We will continue developing and maintaining Volto as we know it today. Volto 19 is scheduled and its roadmap is clear and will happen in the upcoming months.

We will develop the successor of Volto (codenamed Seven, the final name to be decided in the future) in its own branch along side Volto (in main branch) as it happens during the next months.

Since Volto only relies in @plone/registry it should be easy to keep compatibility so it can be used by Volto and Seven. The rest of the Plone frontend modular packages (@plone/*) will continue evolving and used by Seven. It is recommended that none of them become part of Volto core for the time being.

We compiled the Seven Mantras of Seven:

  • "Use the standards, the framework and the ecosystem in your favor as opposed to fight them"
  • "If it ain't documented, it's broken."
  • "Document as you didn't have 20 years of Plone experience"
  • "Prioritize practical client feature requests"
  • "Provide a clear upgrade path forward from Plone 6 to Seven"
  • "Deprecated and unmaintained mean exactly what it's supposed to mean"
  • "Implement features if they have a clear and real use case: stop working for imaginary people"

We should remember and come back to them when a doubt or implementation detail arise in the future.

Deliverables

The Seven app is already in place in apps/seven. It is a React Router 7 app and will be the base of the Public UI, completelly detached from the CMSUI part.

The CMSUI app is also in place in apps/quanta. It is a React Router 7 app based on the Seven backbones and it's the base where the CMSUI will be built. The CMSUI will be in their own add-on: @plone/cmsui located in packages/cmsui.

You would be able to use the same add-ons as in the public UI, so both can share the features, theming and customizations. As they will be separated builds, the public part will be quite thin and lightweight, with the ability to be deployed wherever a React Router 7 can be deployed (Clouflare, Edge providers like AWS lambdas, Vercel, Netlify, etc). The CMSUI could be traditionally deployed alongside the public UI or in a separated server or even encapsulated in a desktop app or in a native mobile app for convenience.

Both apps will be pluggable with add-ons, as in they are meant not to have any code in it, but the boilerplate that will pull other pieces together. These apps would be the ones that the projects will run and inject their own project add-ons to customize them.

The basics and some acceptance tests are already in place in both Seven and Quanta apps.

Complete developer documentation.

More deliverables are described in the related PLIPs or sub-issues of this PLIP.

Guidelines and Quality Gates

Documentation

Documentation is paramount. Something not documented is broken and by definition, it does not exist. Document as if you have not years of Plone development. Do not take anything from granted. Anything that is not documented must not be merged.

TypeScript

All code from now on, should be written in TypeScript. We will be following a pragmatic approach, though:

  • Typings should go in your favor, not in the middle to stumble upon.
  • Don't try to be TS smartypants, nobody expects you to be a TS wizard, nor you should expect this from any of your fellow contributors.
  • React TS is simple, it's about typing props and function args. We are not building complex libraries.

If you are still not sold to TS, you'll be soon, you have trust and to give it a try. This article is good:

https://www.epicweb.dev/typescript-what-s-the-point

If you are still not confident about TS, there are wonderful free resources:

TypeScript Official Handbook

TotalTypeScript React with TypeScript Free course

TotalTypeScript Beginner's TypeScript Free course

We promise that we will use TS in the way that it will be fun, not a burden.

Storybook

Storybook is a very useful tool to showcase components (specially basic ones) and their features and use cases. We will create one every time that make sense. All @plone/components components that we develop must have one.

Acceptance tests

Acceptance tests are the only thing that separate our code from regressions happening. Having the maximum amount of them are crucial.

Accessibility tests using axe-core are mandatory for testing full pages from an integration point of view.

Unit tests

An acceptance test can replace a unit tests, but they are inherently more time consuming at execution. However, unit testing with snapshots are just a bit more than useless. So prefer an acceptance test before a unit test, specially in component testing.

On the other hand, always provide a unit test in case of a helper function.

It's easy to setup a unit test for checking a11y, using axe-core. It is encouraged to test every component if it passes accessibility tests. These are quicker than testing in in an acceptance tests, which should test for a11y on full pages, from an integration point of view, rather than per components.

Risks

Documentation first is a must. It is mandatory that we shape the documentation and validate this documentation with people external to the project.

Coordinate such an effort will be hard, we have to plan it carefully and split the tasks in different parts. There are still things to be decided in several key places, and some others that need to be investigated, PoC'd and test drive them.

Participants

Víctor Fernández de Alba (@sneridagh) Piero Nicolli (@pnicolli) Steve Piercy (@stevepiercy) Volto Team (@plone/volto-team)

[!IMPORTANT]

This PLIP is for Plone's core developers and the subsequent issues are part of the organization of this project. It is not intended for newbies or first time contributors.

sneridagh avatar Feb 02 '25 11:02 sneridagh

Mantra 5: "If it ain't documented, it's broken."

stevepiercy avatar Feb 02 '25 11:02 stevepiercy

Hi. It would be great to explicit about the following

  • What does the non-React story look like for the Public UI?
  • How will live-editing work between the Public UI and the CMS UI if they aren't directly linked?

djay avatar Feb 03 '25 15:02 djay

@djay I will continue adding info to the PLIP. My goal is to have the full plan in there before this year's sprints start. It's important that we are all in the same page, and we all understand the vision. However, this is no difference from what I told in my PC talk, and I'm telling the last two years, the original plan has changed a bit, in execution, but the intention is the same as before.

What does the non-React story look like for the Public UI?

Non-React? What do you mean? We don't have a non-react story so far in Plone. We could have one, at least if someone wanted to push for one. All the PoCs in the apps folder are React based frameworks, so far. What do you have in mind?

What is clear is that the official and what I always called "reference" implementation of both the public and CMSUI have to be React-based. There's no point in other choice.

The story of the @plone/* packages already try to be as agnostic as possible, or serve as "reference" for someone that wants to replicate how they work and their purpose and function in another platform. @plone/client aims to be agnostic, I know that @ebrehault uses it in Svelte. But there is a limit to that, of course, where you can't go further.

How will live-editing work between the Public UI and the CMS UI if they aren't directly linked?

Why do you need them to be linked, if they are able to provide the same output? How would you know that they are not linked at all if you have something in the routing that provide the seamless integration? It's what I never understood from your take on "headless". I think you underestimated the power of @plone/registry add-ons. You can have the same set of add-ons in both sides, still deliver a fast public UI without a bloated build being able to be deployed anywhere in the cloud where a React Router 7 app can be deployed (Clouflare, Edge providers like AWS lambdas, Vercel, Netlify, etc).

I hope we can make seamless integrations, using tools that allow you connect "a la WSGI" different applications under the same umbrella (eg. Vinxi) or fake it using deployment routings in the reverse proxies. Still to be investigated.

sneridagh avatar Feb 03 '25 19:02 sneridagh

@sneridagh

  • I get that your design reduces bundle sizes.
  • I get that you think using react/next.js is supporting what's the most popular so is good enough for most people (although history tells us that doesn't always work out)
  • I get that you no longer use the word headless to describe volto and instead talk about "api-first".
  • I also get that you can't make a CMS to please everyone and maybe volto is aiming more for the site builder market where you don't use code much to achieve very unique designs but instead you tweak the blocks and structure you are given.

But you are using words like "decoupled" and a "reference implementation" for the frontend which make it seem like there is something headless in the design so I think for the sake of clarity it would be useful to understand what the headless story is. And I watched the videos and read these PLIPs and myself and my developers are still confused. All the sites we build now are headless so it matters to us.

When I say headless CMS it's not my "take". Wikipedia says a headless CMS is

a back end-only web content management system that acts primarily as a content repository. A headless CMS makes content accessible via an API for display on any device, without a built-in front end or presentation layer. [1]

Whereas a traditional CMS typically combines a website's content and presentation layers, a headless CMS comprises the content component and focuses on the administrative interface for content creators, the facilitation of content workflows and collaboration, and the organization of content into taxonomies.[2]

The key thing here is the administrative interface/backend (what you call the CMSUI) doesn't make assumptions about the presentation layer/frontend (what you call public UI). So a developer knows they have flexibility. There are no implicit assumptions the administrative interface forces on the frontend implementation like css, base components, frameworks, specific blocks or structure of the page.

Again this is not me saying this

This separation means that the content stored in a Headless CMS is not tied to any specific output format or layout. MACH Architecture

So the question still is, what is the edit experience like, if I can't use the public UI framework? or, if I want to get to a volto like editing experience, what are the options for an integrator, if any, if you can't use the public UI framework?

To make it more clear lets take a concrete example.

For example, in @pnicolli excellent talk on headless with volto - https://www.youtube.com/live/6eV95j1QID4?si=WnYySGdAr87Zw1j6

  • they couldn't use volto for the frontend. but they did use plone/registry and plone/components
  • instead they built a frontend for a mobile hybrid app not using volto (and interestingly mentioned that in some ways this was easier than customising volto)
  • for the administrative interface they used a preexisting theme they had that the client liked. It fit the data model and blocks structures they needed so the fact that it didn't look exactly how the final result looked was not so much a problem.
  • The edit experience was not a single window. They would use volto to edit with a preview that didn't look like the frontend. And on save an editor could go to a 2nd window, refresh the frontend and see the result.
  • For this use case this worked out ok, esp since they didn't have to make any custom blocks twice (once on the edit/volto site and again on the presentation layer/frontend since the volto side was done for them.

So taking a similar example. Lets say you can't use next.js, instead you have to use Astro. so you can use react and plone/registry and plone/components. You have a preexisting design system with it's own blocks and own css all in Astro.

  • what would you have to do to get the single window admin interface experience? what extra do you have to include or rebuild?
  • or is a single window administrative interface not going to be possible? are you forced into using two window editing and making any site specific block again in volto as the only option for headless?

How would you know that they are not linked at all if you have something in the routing that provide the seamless integration? It's what I never understood from your take on "headless"

If you could explain what you mean it would be very helpful to me. DM if you want. I've tried to decypher but so far no luck. We put a lot of time into hydra.pretagov.com demo to prove you can have a single window administrative interface just as good as volto while making no assumptions about the frontend at all, ie headless, in fact visual headless. We did this to try and send plone in a direction that's better for all of us long term. You think there is a tradeoff with hydra that I'm not seeing so it would be really helpful if I could understand what that is to see the error I've made.

djay avatar Feb 05 '25 06:02 djay

What I'm hearing from you two is:

  • Dylan wants to make sure it's possible to render the (public) frontend using a separate application that might be in a completely different framework (and ideally using Hydra-like approaches to integrate the public view into the editor)
  • Victor wants to make sure it's possible to render the (public) frontend using a separate application that uses some of the same components as the CMSUI.

These visions don't sound fundamentally incompatible to me.

davisagli avatar Feb 05 '25 07:02 davisagli

What I'm hearing from you two is:

  • Dylan wants to make sure it's possible to render the (public) frontend using a separate application that might be in a completely different framework (and ideally using Hydra-like approaches to integrate the public view into the editor)
  • Victor wants to make sure it's possible to render the (public) frontend using a separate application that uses some of the same components as the CMSUI.

These visions don't sound fundamentally incompatible to me.

They aren’t incompatible but, hydra gets you more and with less redevelopment and disruption.

Let me explain now that I understand seven more clearly after to speaking to victor.

Sevens goals seems to be a) modernise the frontend and the editor and change it's stack to something more commonly used.
b) allow you to deploy the frontend without the editor so you can reduce its bundle size

But

Headless == you can deploy the frontend without having to redeploy the backend.

So Seven is still not a Headless CMS approach. It is a frontend framework + editor and even if they can be deployed to different places they are coupled. If you change the frontend you need to redeploy the editor. That is because to get visual editing you have to do things the seven way. You have to theme and use seven components. If you add a new block on your frontend you have to make editor changes to make it look anything like what the frontend looks like. The code is mixed and has to be compatible. It is a monolithic approach (well technically they call this “decoupled" but not headless…)

For those used to monolithic CMS and already in the plone community this is no problem. We are all happy learning yet another approach to theming and throwing away our existing themes and redoing it again for this upgrade, esp if we have customers with big pockets.

But unfortunately the rest of the world can’t afford this.

  • if I am a frontend developer picking a CMS am I not going to pick one that requires me to learn it’s frontend framework. I will stick to the frameworks I know and the cms is just an api I can use.
  • If I’m a CTO am I going to pick a CMS that I can, in the future, reuse the frontend I spent money on building should I need to change my CMS.
  • if I am digital agency I will pick a CMS I can get cheaper generic frontend developers, or even outsource the frontend completely and then require fewer resources skilled in CMS customisation. CMS is now an api rather than a way of life. That is why headless is the increasing the most of any CMS segment.

A Hydra type approach on the other hand is not coupled. It doesn’t make assumptions on how you build your frontend yet still gives you a visual editing the same as volto. It puts a web api between the frontend and the editor. It let’s you turn any existing frontend component into a inline editable block using a few annotations. There is no mixed code. and frontend changes require no redeployment of the editor. If Plone would focus on being a CMS and editor not a frontend framework as well then the seven effort would be half the work. It would be a true headless CMS with visual editor and open source and therefore something those outside of plone might be interested in. and as a bonus it would allow old volto frontends to reused with later volto releases saving money for everyone already using volto.

djay avatar May 29 '25 10:05 djay

What I'm hearing from you two is:

  • Dylan wants to make sure it's possible to render the (public) frontend using a separate application that might be in a completely different framework (and ideally using Hydra-like approaches to integrate the public view into the editor)

I should clarify this @davisagli .

What I wanted to was to not see scarce community effort wasted. I spent 20 years in this community and built my business around it.

It's not that I want to render frontends in different frameworks. That can be done. I just won't use seven to do it because it would take double the effort. There are plenty of headless CMS to choose from (just without the visual editing). I've no problem using next. This isn't the point at all.

We have volto sites that I want to not spend large amounts of money on maintaining and upgrading. If things go well we will add the hydra layer of insulation between volto the editor and our frontends and eventually rewrite those frontends. The result would be the best Visual Headless CMS on the market and it would be open source. But the way things are going with everything getting rewritten to benefit few and not grow the community, I'm not sure that makes sense risk wise.

So what I really wanted was to see if I could reduce the risk in this investment by helping plone growing it's community. if I somehow managed to make it clear above why the future is headless and why seven is not that then it should become clear what I want?

One other thing I didn't make clear is the headless approach absolutely doesn't preclude an out of the box approach where you reuse components between the editor and the frontend. It just shouldn't require it to get visual editing. Also I believe that an out of the box experience is just not what the market we are all in wants. Out of the box approaches are handled well by site builders. We all want custom frontends.

djay avatar May 30 '25 04:05 djay

@djay What I was trying to say is that if the Seven CMS UI takes a Hydra approach (I still haven't wrapped my head around how big of a lift it is, but I'm open to it personally), then the Seven public UI just becomes one example of various public frontends that are possible.

I don't really get your point that using Hydra would reduce effort. We would still need to build at least one public UI as an example of how to do it, and as a way to test that it works.

I also don't follow the point that Hydra makes it possible to redeploy your frontend without redeploying the editor. The editor still needs to be updated if there are changes to the available blocks and their schemas, right? Or did you just mean in the case where you're changing how the blocks are rendered without changing the schemas?

davisagli avatar May 30 '25 06:05 davisagli

@djay What I was trying to say is that if the Seven CMS UI takes a Hydra approach (I still haven't wrapped my head around how big of a lift it is, but I'm open to it personally), then the Seven public UI just becomes one example of various public frontends that are possible.

Yes correct.

Hydra approach is this. you use an iframe and postMessage to create a bidirectional communication channel between the editor and the frontend. So where volto/seven would have rendered the page in the middle of the editor itself, you replace that with this iframe and render the actual frontend.

| toolbar |   iframe (frontend)    |  sidebar |

There is a slim pure javascript client inside the frontend running when it's in this edit mode and that does things like handle the few parts of the editing experience that has to be done inside the iframe, like block selection, DnD and inline editing, quanta toolbar. As much as possible is done inside the editor code instead. The state is synced between the editor and the frontend when changes are made to either. You make a change in the sidebar, its sent via postmessage. You click the inline add button inside the frontend and it tells the editor to pop up the add chooser. You add the new block and the editor sends an updated state across with the new block in it. In reality its not that big a lift. But it is throwing away a bunch of existing editor code like how slate and DnD work using react and replacing them. and there is no need for shared components. But it works. You can try the demo https://hydra.pretagov.com/ And we are not alone in doing it this way. This is how storyblok and others do it.

I don't really get your point that using Hydra would reduce effort. We would still need to build at least one public UI as an example of how to do it, and as a way to test that it works.

Because seven is trying to make a theming system like volto whereby you start with shared components and have ways to style and customise them. And they have to work both in the editor and in the frontend. That is a very different and more complex approach to assuming everyone will just throw away your example and use their own components. An example frontend is just an example not a framework. Most headless CMS don't tend to come with example frontends. They often come with no inbuilt blocks or layouts. They tend to not make assumptions and promoting a single frontend would signal your CMS has likely made assumptions.

The other part of the reduced effort is on everyone with existing volto installs. A plugin for an existing volto frontend could be made reasonably easily so it works with a hydra/seven editor. Seven can't. And that keeps applying for every upgrade going forward so the effort savings keep adding up. We can't even justify the cost to our clients to upgrade to volto 18 let alone seven, so how do we get any bugs fixed in the editor that have nothing at all to do with our frontend implementation? And now when we are trying to fix new bugs we find we have to do it twice in order to push it upstream?

I also don't follow the point that Hydra makes it possible to redeploy your frontend without redeploying the editor. The editor still needs to be updated if there are changes to the available blocks and their schemas, right? Or did you just mean in the case where you're changing how the blocks are rendered without changing the schemas?

In the current hydra code you can add and change block schemas with configuration sent using postMessage. As soon as you login the editor knows about the blocks this frontend expects. It works well. But other headless CMS will solve this by putting hte schemas into the database and configuring them via the web. It's helpful to remember that most headless CMS are saas so you can't deploy them. Of course being open source would mean customizing the editor is possible but we don't have to make it compulsory as its really not needed in the fast majority of cases. Adding in schemas and using container blocks gets you a long long way.

djay avatar May 30 '25 07:05 djay