Render WordPress page builder blocks in Next.js / React.js? - reactjs

Headless WordPress (CMS), that is use a page builder (Elementor, Gutenberg etc') to write content.
Then render the content elsewhere, using Next.js (React.js).
I can easily get the HTML markup, but the styling is challenging.
I could also get the inner data structure, for example Elementor is using JSON, but that means I should implement each component - unwanted.
How would you approach this, considering WP headless + Next.js is a requirement?

In a similar situation - there's no easy solution. Page builders are dependent on lots of WP-specific code. Unless you need specific WP plugins to power parts of this, it's probably a lot less work to adapt ApostropheCMS to whatever your needs are.

Related

How to set dynamic metatags in ReactJS to get nice share links?

The app
The application was made using ReactJS, React Router Dom, Styled Components and Redux ducks.
The backend we consume is also made by us using Amazon Amplify and GraphQL.
The goal
We need to define the meta tags of one of the application pages so that it is possible to share personalized links to users
in social networks using OpenGraphic meta tags and the like.
The problem
The project was made in ReactJS and ReactJS has only one HTML page as root (/public/index.html), in this way, everything is generated with Javascript in a root tag, and when it arrives in the browser it is transpiled, as we already know. The problem is that the crawlers responsible for understanding the meta tags are not able to understand Javascript and end up not finding the dynamic data that I am defining on the page that I need to share the link on. They understand that there is one html file and only.
Attempts to resolve the issue
1) Define the meta tags in the /public/index.html file itself
This solution doesn't work because the data we are using is dynamic and the index.html file is a static file
2) Using react-helmet
The solution allows meta tags to be defined, but as already mentioned, crawlers don't understand JS. So, despite being on the page, the meta tags do not appear when sharing the link.
3) Using some SSR technology
This is a possible solution, but we were unable to integrate any SSR Framework into React. And it is not feasible to change the base technology of the project. We can't just switch from React to Next, for example, as the project is already complete.
4) Using a small server made with express.js along with the React application to replace the meta tags in index.html with string.replace() simulating something like an SSR
This solution works, but it causes two requests to be made every time the page is accessed, once by express.js and once on the front-end side by React. Due to the number of requests increasing, this solution was discarded. But if necessary, you can do it. In this case it is also necessary to check if Amplify can keep the application and the small server running in the same project.
5) Using react-snap with react-helmet
React-snap allows you to create html snapshots of the pages of a React project based on their routes and links, this added to react-helmet generates a perfect solution for links to be treated well by web crawlers when they are shared. But the solution doesn't work with dynamic routes. For example, /your-route/:id is a dynamic route that expects an id to be fully defined. React-snap gets lost when trying to create a snapshot of a route that only exists when the id is set. Unfortunately, this solution doesn't work.
These were the solutions we used to try to solve the problem, but it was not possible yet. Probably attempt 4 would be the most ideal to solve the problem. But we are looking for the best way that will not generate reworks and future problems. If someone knows a better way to do that, would help us a lot!

How to use Flask to serve a React.js single page component

I have an application that is largely tables and standard pages and forms. However, I have one page this really need to be highly responsive that is probably best developed in React.js.
I would like to have a Flask + Jinja handle the delivery of most of the pages. I understand Facebook does a bit of this with PhP for the majority of the site with React.js handing the responsive components. Is there a Flask library that makes this simple?
I don't think you need to use any library for this as it's pretty straightforward.
All you need to do is:
Make that page using React.js and build the project to make bundle Javascript file which bootstraps the React.js page.
Make div inside your jinja template and import that bundle javascript file.
Here, one important thing is to assign identical 'id' to the Jinja template div and React.js rendering div.

Is it possible to use React components to author AEM Experience Fragments, which then feed a headless frontend?

To briefly describe my goals --
I have an external React component library of ~70 React components, which feeds a web frontend (Websphere Commerce site, which pulls in Experience Fragments via AJAX calls to get the fragment HTML), and also a React Native app. So for the web, AEM is basically the content engine which feeds our headless frontend.
I'd like to use those same React components to feed the AEM Experience Fragment authoring experience, instead of having to rebuild each React component as an HTL template within AEM -- it's too much overhead to maintain a completely separate component library of HTL templates
By following the official Adobe tutorial here, I see how it is possible to map React components to the Content Fragment authoring experience. By which I mean, if I go to AEM Home > Sites > (my site) > create a new fragment, the component I drag in is fed by a React template. I can tell, because the markup matches what is in my BasicComponent.js React template in ui.frontend, and not the basic-component.html template in ui.apps.
But, if I go to AEM Home > Experience Fragments > create a new fragment, that same BasicComponent component will pull from the basic-component.html file in the component folder (next to .content.xml), instead of from BasicComponent.js
I'm new to AEM, so hopefully the above makes sense. I know I am missing something pretty fundamental re: how Experience Fragments differ from Content Fragments (if that is the right term). I've spent a lot of time Googling around for information, but I'm finding that my own ignorance is making it difficult for me to determine if what I'm reading is or is not a clue to solving my issue.
This is the repo that I pulled down to experiment with: https://github.com/drginm/aem-react-simple-example
Any help much appreciated! I'm sure I'm not the only AEM newbie looking for an approachable model for handling this situation.
Experience Fragments is not recommended used with ajax html in headless architecture, it should be exposed via sling model exporter in json format for the react consumption.
To edit and modify the experience fragments AEM doesn't provide any APIs, AEM developer should give custom REST APIs to do the changes.
I would recommend to go with the content fragments where the CRUD operation is possible via Assets api in AEM.
References
Difference between experience fragments and content fragments
ASSETS API for the Content Fragments

Dynamically Generating Routes in Gatsby JS

I am trying to create a complex CRUD React Application using Gatsby JS. The ability for the user to Create Posts, Edit Posts, Delete Posts will also need to be available. This app will have many users. We are not using a third-party CMS. Everything will be done within the Gatsby App. There will also need to be several different pages that will need to handle state, display, and sort the different posts based upon options. My question is, is this sort of project overload for Gatsby JS since it breaks the page model? Gatsby doesn't have a native way to generate dynamic routes or views, only pages. Its sort of a social networking app, is Gatsby JS the wrong tool for the job?
You can create pages "dynamically" using the createPages API.
https://www.gatsbyjs.org/docs/node-apis/#createPages
There's also a great series of videos from Scott Tolinski that demonstrate the use of this API.
However, GatsbyJS is a static static site generator, it's designed for performance and more content-based sites. The only way you're going to get CRUD functionality is through API calls from the front-end which could have some security implications that you need to consider.
As an alternative, you might want to take a look at Next.js. Same kind of idea but the pages are served by Express.js rather than just served off the file system so you have a lot more options for more dynamic sites.

Accelerated Mobile Pages (AMP) strategy/ implementation for AEM

What is the best approach/ strategy to implementing Accelerated Mobile Pages (https://www.ampproject.org/) within AEM 6.1 for a responsive web site that already renders for both desktop and mobile?
An initial concern is that you would be creating duplicate pages of content. So is it possible that AMP and normal html can share the same content?
Would you always redirect to AMP if mobile, and what is the best way to do that?
How would an author handle both AMP and standard pages?
More information is required to completely answer your question -
What is your approach towards responsive design (if you are supporting desktop)? Are mobile site and desktop site different?
What version of AEM are you using?
How would an author handle both AMP and standard pages?
Authoring is something which is not AMP specific, AMP is a feature/behavior that you would enforce on Publish instance and not Author. But this depends on your approach towards responsive behavior - single site handing both mobile and desktop or separate?
a) If there are separate sites then you would actually cater to AMP behavior on author as well by having different components/resource types and page templates for it (This is how prior to AEM 5.6 mobile sites were handled). I can provide more details if you are following this approach
b) If there is single site then you should configure this at publish only.
is it possible that AMP and normal html can share the same content?
In short Yes, depends on how you design your components and/or what version of AEM are you using. In AEM 6.2, Adobe has introduced content fragments that allows channel agnostic content management i.e. more like assets.
If you are not using AEM 6.2, even then you can allow for reusable content by designing for it. You could create a global space with content pieces and then use reference component to associate/use that content on different pages (the only challenge with this is to manage full text search if you have that on your site).
Would you always redirect to AMP if mobile, and what is the best way
to do that?
What ever approach you take a) or b) (as described in first answer), the essence for managing the redirects/rewrites is to exploit user-agent information in request. Apache/httpd allows to handle user-agent information and do a redirect of rewrite.
For approach a) you will redirect to your mobile site after identifying that user-agent is mobile user-agent and for approach b) you could rewrite the url (not redirect) add a selector that allows for you AMP specific resource scripts to render the content. Selector based solution is one possible way of implementing the single site for both web and AMP
UPDATE:
Assuming that you need to cache both AMP version and normal HTML markup, the solution is to use a special selector for rendering AMP version of markup. You could setup a component hierarchy -
Lets say your base page structure is abstracted out in a custom component called - AbstractPageComponent (this in most cases is replica of foundation/components/page customized to project need) and all your page components extend this component. What you could do is create another such component lets say AMPAbstractPageComponent, setup this page structure similar to standard Abstract component i.e. let it have its own copy of scripts head,body,content, header,footer etc. But make sure you name them differently from the convention in AbstractPageComponent, u could do that by pre-pending amp to them like amp-head.html, aem-body.html,amp-content.html. Then there will be AMPAbstractPageComponent.html the component rendering script that structures the page by including relevant AMP scripts and/or AbstractPageComponent scripts.
Each of these scripts should have the AMP specific logic and where-ever you need to refer to HTML logic include/defer to the AbstractPageComponent's script.
Now define the selector script to ensure AMP specific rendition, let say your selector is amp then in AbstractPageComponent create a amp.html or amp.jsp and in this script include AMPAbstractPageComponent.html
NOTE: The ideal structure to implement will be foundation Page -> AbstractPageComponent -> AMPAbstractPageComponent -> Other page templates
I have specified AMPAbstractPageComponent to be parent of AbstractPageComponent assuming that your site already exists and there is content pages referring to existing structure. If your site structure permits you to introduce AMPAbstractPageComponent between AbstractPageComponent -> Other page templates then you should do that and let AMPAbstractPageComponent handle that amp selector.
What i have defined above is the first level of change, next you need to consider the components inclusion that have AMP specific handling. For components included in templates you need pass on the selector amp if its coming in the URL otherwise included component will render their default script (component included in the templates not drag and dropped components).Dragged and dropped components will automatically try to render amp script if available and in case its not then default to its own script.
Please note, this is approach based on the selector resolution, for actual implementation to do AMP specific work you may have to do other stuff as well, another thing i have not included is the managing component rendering i.e if you normal html includes a parsys and that script in not included in your AMP implementation your components will not render. So you will either have to duplicate those inclusions in AMP specific scripts or you will have to include the AbstractComponent's scripts to include such components
Do a small PoC, I gave the approach solely based on high level understanding of what AMP does by reading the link you have specified.
I'm actually thinking about implementing the same and here is the thought path laid out so far (untested):
add new page extension handler at foundation/components/primary/cq/page (overlay it under /apps) named Page.amp.jsp with <%#include file="proxy.jsp" %> content
add page renderer into your application logic at the same place where are you rendering html pages
The rest should be done by ootb sling URL resolution handler

Resources