Part 3: Building a simple application using the Entando ACP

sohinip

Sohini Pattanayak

Posted on March 9, 2022

Part 3: Building a simple application using the Entando ACP

In the previous blogs, we learned about the 4c’s and we also installed Entando on our local machines. In this blog, we are going to implement the 4c’s to create a very simple bundle and deploy it to our Entando Platform.

The question is, what is a Bundle?

An Entando Component Repository or ECR bundle is a package containing one or more components and a 'descriptor.yaml' file providing information about the bundle. The bundle is published on a Git registry and is shared with an Entando application using the EntandoDeBundle custom resource.

At first, we will create a widget that we would deploy to our Entando Platform. So currently, we are working as a creator. To do so, we’ll open up our favorite code editor/terminal, create a new folder and name it: product-listing.

A little idea about what we’re going to build. We’ll build a simple React application that displays a few cards with some data on them, and this is what we define as our micro frontend (MFE). Then, we’ll run and build the React MFE. We next bundle up the entire MFE using ENT CLI and deploy it to the Entando Component Repository. Finally, we’ll install it in our App Builder, and drag and drop the cards widget (the one we created in React) to our Page!

Well, it might sound like a huge project, but it’s easy.

To begin, we will refer to this GitHub repository. This repository is an Entando project template that helps us to create a micro frontend, microservice, or both. Since we’ll focus on the micro frontend today, we’ll delete unnecessary files and folders from this project template, after we clone it. We’ll also rename the folders with respect to our project. And then copy everything inside the product-listing folder that we created previously. It should typically look like the structure below:

Image description

Inside the widgets-dir folder, the cards-widget folder is the React app that we create, as I’ve deleted the existing widget et-app from the widgets-dir folder. We can name it as per our own preference. I’ve created mine:

Image description

For the bundle_src folder (inside product-listing directory), we can see a descriptor.yaml file. In there, we need to paste the following yaml code:

code: product-listing
description: Template for simple cards design
components:
 widgets:
   - ui/widgets/widgets-dir/cards-widget/cards-descriptor.yaml
Enter fullscreen mode Exit fullscreen mode

This is a yaml file, through which we are telling the Entando Bundler that our widget is present inside the cards-widget folder. And we are pointing it to the cards-descriptor.yaml file that is present inside another bundle folder (one that we create inside our React app i.e inside cards-widget directory). If we have more widgets inside the widgets-dir folder, then we need to add them here too.

Now, I’m assuming you have followed the above folder structure and created a bundle folder with a cards.ftl file and a cards-descriptor.yaml file inside the cards-widget folder. Hence, we go to the cards-widget > bundle > cards.ftl file and add the following content:

<#assign wp=JspTaglibs["/aps-core"]>
<#-- entando_resource_injection_point -->
<#-- Don't add anything above this line. The build scripts will automatically link the compiled JS and CSS for you and add them above this line so that the widget can be loaded-->

<@wp.info key="currentLang" var="currentLangVar" />
<cards-widget locale="${currentLangVar}"/>
Enter fullscreen mode Exit fullscreen mode

That’s it for this .ftl file. What typically happens here is, when we build our project using the ENT CLI command, all the build scripts and link tags appear here.

Under the same bundle directory, inside the cards-descriptor.yaml file, we add the following code:

code: cards-section
titles:
 en: Sample Cards Section Template
 it: Sample Cards Section Template
group: free
customUiPath: cards.ftl
Enter fullscreen mode Exit fullscreen mode

So far, we have filled all our descriptor files, ftl file, and have created our React app.

We keep the prepareBundle.sh and prepareMicrofrontend.sh files untouched, as they act like the engine of our machine!

Now that we are all done configuring all the files, we jump inside the cards-widget folder and start designing our React app to display a set of cards. Inside the src folder, we create a new file and name it cards.js. We open up a terminal inside this directory and add a package to use bootstrap:

npm install react-bootstrap bootstrap@5.1.3
Enter fullscreen mode Exit fullscreen mode

Image description

Now we add the following code to our cards.js file:

import "bootstrap/dist/css/bootstrap.min.css";
import { Card, CardGroup } from "react-bootstrap";

export default function App() {
 return (
   <div>
     <CardGroup>
       <Card>
         <Card.Body style={{ backgroundColor: "#F4ECF7" }}>
           <Card.Title>Much Scalable</Card.Title>
           <Card.Text>
             Our product xyz is very scalable and has grown a lot in the past 2
             years. More extra text here to explain.
           </Card.Text>
         </Card.Body>
         <Card.Footer style={{ backgroundColor: "#D6EAF8" }}>
           <small className="text-muted">Last updated 8 mins ago</small>
         </Card.Footer>
       </Card>
       <Card>
         <Card.Body style={{ backgroundColor: "#F4ECF7" }}>
           <Card.Title>Very Fast</Card.Title>
           <Card.Text>
             Our product xyz is very fast and has proven itself a lot in the
             past 2 years. More extra text here to explain.{" "}
           </Card.Text>
         </Card.Body>
         <Card.Footer style={{ backgroundColor: "#D4EFDF" }}>
           <small className="text-muted">Last updated 3 mins ago</small>
         </Card.Footer>
       </Card>
       <Card>
         <Card.Body style={{ backgroundColor: "#F4ECF7" }}>
           <Card.Title>Free to use</Card.Title>
           <Card.Text>
             Our product xyz is absolutely free to use and is available to
             download directly from our website. More extra text here to
             explain.
           </Card.Text>
         </Card.Body>
         <Card.Footer style={{ backgroundColor: "#FCF3CF" }}>
           <small className="text-muted">Last updated 4 days ago</small>
         </Card.Footer>
       </Card>
     </CardGroup>
   </div>
 );
}
Enter fullscreen mode Exit fullscreen mode

And in our app.js file, we replace the existing content with the following:

import "./App.css";
import Cards from "./cards";

function App() {
 return (
   <div className="App">
     <Cards />
   </div>
 );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Now that we have created our application, we need to wrap the entire React app into a custom element. Hence, we add a new file src/WidgetElement.js with the following custom element:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

class WidgetElement extends HTMLElement {
 connectedCallback() {
   this.mountPoint = document.createElement("div");
   this.appendChild(this.mountPoint);
   ReactDOM.render(<App />, this.mountPoint);
 }
}

customElements.define("cards-widget", WidgetElement);

export default WidgetElement;
Enter fullscreen mode Exit fullscreen mode

Then, open src/index.js and replace the entire file with these two lines:

import './index.css';
import './WidgetElement';
Enter fullscreen mode Exit fullscreen mode

Lastly, we go to public/index.html andreplace <div id="root"></div> with the custom element <cards-widget />, like this:

<body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
     <cards-widget />
</body>
Enter fullscreen mode Exit fullscreen mode

Perfect! Now, we need to build our React app before we build the entire bundle.

Image description

To do so, we run:

npm run build
Enter fullscreen mode Exit fullscreen mode

Image description

We go to the root directory of the project. In our case, it is product-listing, and set up the Project Directory:

To follow the steps below, we need to have our terminal open on the root directory. Then, we can run the following commands in the terminal.

  • Prepare the bundle directory cp -r bundle_src bundle

Here, the descriptor.yaml file gets copied to the bundle folder, where all our static resources will be created when we build the bundle going forward. So, in a way, we are preparing the bundle folder.

  • Initialize the project: ent prj init
  • Initialize publication: ent prj pbs-init

In this phase, we need an empty GitHub repository that we link here for our bundled code to be pushed to. This repository should be named like: product-listing-bundle

Image description

  • Attach to Kubernetes for an Entando application via ent attach-kubeconfig config-file or similar.

Now, we publish the bundle to Entando App Builder:

  • Build: ent prj fe-build -a (to just build the frontend, including changes from bundle_src)

This is where our bundle is built, and remember i mentioned about the cards.ftl file? That all the script and link tags are injected there? Well, this is the step where it happens. So right after you execute this step, you can go to the cards.ftl file inside your bundle folder of the React app, and you’ll see those tags.

Image description

  • Publish: ent prj fe-push (publish just the frontend)
  • Deploy (after connecting to k8s above): ent prj deploy

At this point, we are pushing everything to the Entando Component Repository.

Image description

That’s all. Congratulations you just built a micro frontend using React, bundled it and deployed it.

Normally, here starts the Curation Phase. We are not using a Hub here. But, in general, when we have a Hub (The Hub is a central catalog where many curators and teams can share and collaborate on components or bundles. They can publish and manage versions, share metadata and communicate about features.), we publish and deploy a bundle to it. A curator validates it and ensures that components, business capabilities, and solutions are ready for composition, defining prerequisites and updating capabilities with the latest patches or upgrades. In our case, we imagine the Entando Component Repository to be the Hub and we are the curators for now.

Now it’s time we Compose the application from the Entando Component Repository.

At first, we login to our Entando App Builder:

Image description

We first see our dashboard, and from the dashboard, we navigate to the left button of our page, where we see “repository”. Click on it.

Image description

We can see our product-listing bundle here, and so we install it.

Then, we go to Pages from the left sidebar. And click on Management.

Image description

Here we add a page to our page tree, and design its layout to have some page frames, so that our widget(s) can fit. And then we save and design!

Image description

Here we see a list of widgets on the right sidebar, under “users”. We drag and drop the “Sample Cards Section Template” to any part of our page frame and click on publish. Then click on “view published page” and boom!

Image description

Congratulations again! You did it!

So, If people come to use this application, they would be Consumers of our application. But since this was just a demo to understand the workflow, we didn’t actually consume the application!

Well, that was just a little bit, so you understand the process. Like this, a team of many people can contribute to this same application. They can have widgets built in Angular, Vue, or Next.js and have them all here on a single web page. Isn’t that fascinating?

To check out if you’ve missed anything, do take a look at my uploaded source code at GitHub.

With this, we come to the end of our blog series, Getting started with Entando. You can see more blog posts on our website. We’re also building a community, where we can rapidly create a culture of Modular Applications along with you all. If that sounds interesting, do join us on our discord community! Thank you!

💖 💪 🙅 🚩
sohinip
Sohini Pattanayak

Posted on March 9, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related