Backend for Frontend (BFF) for Seven using Nick as BFF
[!IMPORTANT] If you are not a member of the Volto Team or Developers Team in the Plone GitHub organization, then do not work on or comment on this issue.
PLIP (Plone Improvement Proposal)
Responsible Persons
Proposer: Víctor Fernández de Alba (@sneridagh)
Seconder: Rob Gietema (@robgietema)
Abstract
This PLIP proposes the implementation of a Backend for Frontend (BFF) approach for the Plone 7 frontend (Seven), with @robgietema/nick — referred to as "Nick" — serving as a BFF for Seven.
[!NOTE] To clarify, this proposal is not intended to replace anything, but it is intended to provide a new option that currently does not exist. It does not mean converting NickCMS in the default Plone 7 backend. This PLIP is proposing Nick as an alternative backend for Plone 7 frontend for entry level, technology enthusiasts, personal sites, and alike. Implementing this approach has several benefits, like easy and effortless deployment in freemium SAAS (the whole stack) by sharing the same Node (backend) server in the same deployment (do you remember Andy and Pete's big green button?).
Motivation
A Backend for Frontend (BFF) is an architectural pattern in which a specialized backend layer is created to serve the needs of a particular frontend or client application. Instead of the frontend directly consuming a generic or monolithic API, the BFF is tailored to supply exactly what the frontend needs in the most efficient and secure way.
Instead of the frontend talk to the backend crossing the network chasm, accesses directly to the data layer through the BFF API, which matches the Plone RESTAPI 1:1. The backend endpoint logic sits in the same Node server instead of a different one (with its own language, platform and framework), simplifying the deployment dramatically.
Assumptions
- Nick will provide a BFF mode where it does not "open a port", but their endpoints can be used as a collection of API methods.
- Clear and up-to-date documentation is crucial for developers to understand, implement, and extend the BFF architecture and usage.
Proposal & Implementation
- Evaluate and document the requirements of the Seven frontend that benefit most from a BFF approach.
- Adapt or extend Nick as a general-purpose BFF for Seven, covering authentication, content retrieval, aggregation, and additional frontend-specific needs.
- Develop comprehensive documentation on:
- What a BFF is and why it is beneficial for Seven.
- How Nick is deployed and maintained as a BFF for Seven.
- Real-world examples, development workflow, best practices, and migration notes for legacy integrations.
- Create migration and integration guides for existing Volto or other Plone frontends to adopt or experiment with Nick as their BFF.
Sketching an ASCII diagram of the two architectures:
Plone 6 traditional deployment:
Volto -> plone.restapi -> Python Plone -> ZODB/RelStorage/RDBMS
Plone 7 traditional deployment:
Plone 7 frontend -> @plone/client -> plone.restapi -> Python Plone -> ZODB/RelStorage/RDBMS
BFF deployment:
Plone 7 frontend -> nickcms/client -> NickCMS -> RDBMS
Deliverables
- Updated/extended Nick BFF service suitable for frontend needs.
- Developer documentation (guide, how-to, cookbook, migration notes) for:
- Setting up and running Nick as BFF
- BFF architecture overview
- Example projects and migration guides
Risks
- Additional infrastructure and maintenance complexity due to an extra backend layer.
- Possibility of duplicated business logic if not managed properly.
- Need to keep documentation in sync with development.
- Training needed for Plone, Volto, and frontend developers new to the BFF pattern.
Participants
- Víctor Fernández de Alba (@sneridagh)
- Rob Gietema (@robgietema)
- Plone 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.
I have some big concerns about this, but first let me make sure I understand what you are proposing.
I think what you're saying is that instead of calling a backend API which serializes everything as JSON, Seven's loaders would call functions from Nick running in the same Node process. Do I have that right?
For Seven, Nick will act as the BFF, sitting between the backend (or other sources) and the React-based frontend.
This part makes me doubt whether I understood correctly. I thought Nick was a backend itself, not something that sits between a backend and a frontend. Would the existing Plone REST API and Python-based backend stack still be involved here, or not? If not, what is the backend you're talking about here?
Anyway, my concerns are:
- It sounds like it would create too tight a coupling between frontend and backend, and remove a lot of the benefits we got in the past decade by creating the REST API:
- It wouldn't be possible to use the frontend with a different backend.
- It's very likely that backend functionality would get added with only the Seven frontend in mind, without thinking about how to expose it via an API. It would be a return to the Plone Classic days where there are things you can only access via one specific user interface.
- It sounds like it would require a complete backend rewrite and data migration for existing sites. Basically it would be a new CMS, not something most of the community could be expected to move to any time soon.
@davisagli @erral
I didn't wanted to spark controversy with this one: My apologies, because in the last review, the machine introduced some strategic wording that could lead (with good reason) to confusion and cause havoc.
I reviewed and reworded the document. Also, I realized that @plone/client has nothing to do in it.
Quoting @davisagli :
I have some big concerns about this, but first let me make sure I understand what you are proposing.
I think what you're saying is that instead of calling a backend API which serializes everything as JSON, Seven's loaders would call functions from Nick running in the same Node process. Do I have that right?
Yes, that's what a BFF is. Putting all the logic of an endpoint as an API, usable like a library. Then, you don't have to spawn another process and cross the network chasm.
For Seven, Nick will act as the BFF, sitting between the backend (or other sources) and the React-based frontend.
This part makes me doubt whether I understood correctly. I thought Nick was a backend itself, not something that sits between a backend and a frontend.
It is a backend itself, but @robgietema has already initiated the refactoring to be able to consume the endpoints without the Express logic around them.
Would the existing Plone REST API and Python-based backend stack still be involved here, or not? If not, what is the backend you're talking about here?
Sorry about the placement of a "default" in the original text, this is where the machine betrayed me.
I see Nick in the Plone ecosystem as just another deployment option, with no Plone (Python) backend involved. Initially for entry level, technology enthusiasts, personal sites, and alike. By achieving this, we will have access to deploy Plone in any freemium SASS, effortlessly and "just pressing a button". Which is what we've been dreaming since long time ago.
It sounds like it would create too tight a coupling between frontend and backend, and remove a lot of the benefits we got in the past decade by creating the REST API:
Now you have a library, plone.restapi, now you'll have another one, called "nickcms".
It wouldn't be possible to use the frontend with a different backend.
Why not? Consider this pattern:
import PloneClient from 'nickcms/client';
const cli = PloneClient.initialize();
config.registerUtility({
name: 'ploneClient',
type: 'client',
method: () => cli,
});
// Then, in code:
const cli = config
.getUtility({
name: 'ploneClient',
type: 'client',
})
.method()
const data = cli.getContent({ path, expand })
It's very likely that backend functionality would get added with only the Seven frontend in mind, without thinking about how to expose it via an API. It would be a return to the Plone Classic days where there are things you can only access via one specific user interface.
No, if you continue thinking on each API as an endpoint. It's what we want to do in Plone with plone.api, right? One API implementation that hides the real implementation behind. You change the real implementation, the façade is intact. The only thing that we are doing here is eliminating the network chasm.
@sneridagh to clarify, this proposal is not intended to replace anything, but it is intended to provide a new option that does not currently exist. Is that correct?
To sketch an ASCII diagram of the two architectures, is this close?
Present
Volto -> @plone/client -> plone.restapi -> Python Plone -> ZODB/RelStorage/RDBMS
Future
# Nothing changed in this stack
Volto -> @plone/client -> plone.restapi -> Python Plone -> ZODB/RelStorage/RDBMS
# Additional stack option
Volto -> @nickcms/client -> Nick -> RDBMS
Feel free to edit or correct me.
@stevepiercy yes, I added your diagrams to the main PLIP (with a small correction, specifying Plone 6/ Plone 7 differences).
@sneridagh Thanks for the clarifications, it makes more sense now.