Low-code method to surface data from the Common Data Service (Dynamics 365) on a public webpage. NOT using a Portal.

In order to be successful with a career in technology, you must constantly be learning. This may involve reading, taking classes or watching videos. Not only about the Power Platform or Dynamics 365 but learning about other technology stacks and methods, and thinking about how to apply them to your projects.

One week ago I had no idea what JAMstack is, until I watched this amazing video by MVP John Liu; Build Public websites with Microsoft Flow (Flow JAM Stack). Check out John’s video below;

In a nutshell, John surfaces data from a SharePoint list on a publicly facing web page, using Microsoft Power Automate (Microsoft Flow), Azure blob storage and also CloudFlare Content Delivery Network (CDN).

Dynamically creating Static Content

The concept is a simple method of showing data (public and read-only) on a web page instead of using a content management system, a custom web application or even a Power Apps Portal page. A static web page with data content is generated using a static content generator (in this case Power Automate), and then copied to a publicly available cloud storage, where it can be viewed anywhere with a browser.

Since it is a static web page, there is no direct connection back to the source database (making it secure). Each time the content updates on the source data store (e.g. adding a new item to the SharePoint list) a flow is triggered to re-generate the static web page and is uploaded and replaces the previous version on the cloud storage folder. The user viewing the page will be able to access almost real-time updates. The page renders quickly as there are no calls back to the database to query the data. The process is a “push” as opposed to a “pull”.


JAMstack isn’t a specific technology but rather a method to generate web content. The acronym for JAM is JavaScript, API and Markup. There is a lot of good information that explains many of the concepts (along with examples) on the Jamstack website.

Chances are that you have used similar methods before. I remember in the mid-90’s I worked on a simple e-commerce site (selling VHS tapes) that generated HMTL product pages from a Paradox for DOS application. The webmaster would just generate a new set of pages every week from the database and FTP the pages to the web server.

Surfacing Common Data Service/Dynamics 365 Data on a Web Page

After watching John’s video and learning about JAMstack, I began to think of use case scenarios that would relate to surfacing data from the Common Data Service. Using Power Apps Portals, its pretty easy to create an Entity list and surface that on a portal page. However, there are business requirements where a Power Apps Portal is overkill or the licensing becomes incredibly expensive. Even building a custom web application would require development work involving working with the CDS WebAPI and authentication from the web application to access CDS.

The following is a pretty simple example of setting up a “JAMstack” page that will list data from the Common Data Service. There is virtually no coding involved (asides from a tiny bit of HTML). Any maker or functional consultant could easily build and deploy this solution. I followed John’s steps from his video but instead of SharePoint lists, I used CDS.

Backend Model-Driven Power App and CDS

I created a very simple Power App (model driven) that tracks product inventory. This can be built on a vanilla CDS or extending the Dynamics 365 Sales product catalog.

Model Driven Power App (Could be Dynamics 365 App)

Our use case will be to display a webpage listing products from CDS which will be updated in near real-time.

Setting up Azure Blob Storage

We will put our static web page in a public Azure Blob Storage folder. The following steps outline how to setup an Azure Blob storage folder. You will need an Azure account.

The first step is to create a new Azure Storage account. Locate the Storage accounts services on the Azure home page.

Azure Storage Accounts

You will see a listing of your storage accounts, click on +Add to create a new storage account.

Add new storage Account

Choose a resource group to hold your storage account. I like to create new resource groups for each new project and I usually add a prefix of “RG” for easier visualization.

Add resource group

Give the storage account a name and ideally choose a data center. Usually I would recommend the same data center in which contains your Power Platform environment. This isn’t mission critical as there will be no “direct” connection between the web page and CDS. To save a few pennies, choose LRS storage, as our content is dynamically generated from CDS so we don’t need copies in different data centers. Click Review and Create.

Configuration of Storage Account

Verify the settings for your new storage account and click create.

Create Storage Account

The process will take a few seconds, and eventually the storage account is created.

Storage Account created.

We now need to create the container within the storage account to hold the static web page. Locate the Containers tab and choose to create a new container. Choose a name for the container (this will be part of the URL, so keep it short and simple). Also provide blob anonymous read access to allow the world to read your web page.

Set up blob container

You will need an access key to allow access from Power Automate to update the web page content. In the settings tab, find Access keys and copy the key.

Access key

The Azure Blob storage is ready to go. The next step will setup a Power Automate flow.

Power Automate to Create Web Page

Instead of creating a complex web application with authenticated WebAPI calls to CDS to read records and format them into an HTML table, we will create a flow that will read data from CDS, format it as an HTML table, create a simple web page and copy it to Azure Blob storage.

Here is simple version of the completed flow.

Completed flow

The trigger will be a Common Data Service (current environment) whenever a record is created, updated or deleted. This means that any change in products, additions or deletions will create a brand new static web page.

WARNING: In a real world scenario, you might want to filter to only update on key field changes or even run on schedule to limit the amount of flow runs. If you are doing an upload of data (e.g. a migration) it will make sense to pause the flow.

Create a new page for each change

The next step is to collect the list of Product records from CDS using the Common Data Service (current environment) List records action.

NOTE: For any Common Data Service records, you should be using the Common Data Service (current environment) connector wherever possible (even if you are using Dynamics 365). Great post by MVP Sara Lagerquist on the different CDS connectors by clicking here.

In my test scenario, I only have a few products, but if you have 1000s of records, you might want to consider filtering or limiting the data that gets pulled.

Get list of products.

Now that we have our list of products, we can create an HTML table using the Data Operation Create HTML table action.

Create HTML table

Enter the Header labels and choose the fields you want to display on the web page.

Build HTML table

The next step we will create an HTML page using a compose action.

Compose Action

This will require a little bit of HTML coding, but nothing to break a sweat over. Of course you can get fancy and add specialized CSS to make it look pretty. For this example, I am going for functional, not pretty.

Create HTML page

Now that our page is created, the next step is to create it as a file on the Azure Blob storage folder. Add the Azure Blob Storage Create blob action.

Create blob

We need to create a connection to the Azure Storage account to be able to write out web page file. On the action step, click on the ellipse and add a new connection.

Create connection to Azure

Give the connection a name and fill in the Azure Storage Account name and the key you copied earlier. You can return to Azure and generate a new key if required. Note that this does not have to be the same Azure as where your Power Platform environment resides.

Create Connection.

In the blob, choose the folder path, put in index.html as the file name and set the content from the Outputs of the compose action from earlier.

Create HTML file

Testing the flow

Test the flow and if successful, there should be a index.html file in the Azure blob. In the properties you will find the URL to browse to.

index.html file

Navigating to the site you will see the web page. If you hit F12 you will find no connection string or setting to get back to your CDS environment.

Web page.

If you make changes to any of the data in the Power App (create new records, update quantity or price) this will kick off the flow and create a new static web page.

Update record in CDS/Dynamics 365

After a few seconds, refreshing the web page will show the updated data.

Refreshed Data

Content Delivery Network (CDN)

Another thing I learned from John Liu’s video is Content Delivery Networks (CDN).

The CDN is a series of proxy servers that distribute content world wide. John set up a CDN to store his static web page with the idea that it wouldn’t continuously use Azure resources.

For my experiment, I also configured a CDN to distribute my CDS webpage.

I signed up for free CloudFlare account and associated my nickdoelman.com domain name. I added a CNAME record pointing to my Azure blob storage URL.

Add CNAME record

The next step is to turn off the proxy in the CNAME entry to be DNS only. (I would have NEVER figured that one out, if not for John’s video.)

Next, the custom domain needs to be added to the Blob service.

Add custom domain name.

After this step was done, I flipped the CNAME entry in CloudFlare back to proxy.

The page is now accessible via my custom domain name.

Accessing page via CDN

Update (May 1, 2020)

MVP George “The Enabler” Doubinski pointed out that you can post directly to a static website instead of a container. It has benefits of understanding default document (so you don’t need to specify the index.html in the URL), gives you a separate URL with a custom domain, and works with Azure CDN.

Static website


Definitely check out John’s video. His style is great, just starts jotting down some ideas on Microsoft Whiteboard, provides some background and starts building the application from scratch. John has indicated he will be posting more videos implementing JAMstack with Power Automate. I look forward to learning more!

There are a lot of scenarios in which this technique could be applied. It is fast, secure and very easy to setup. Let me know in the comments below if you end using this technique in any of your projects.

Cover Photo by Jonathan Pielmayer on Unsplash

Nick Doelman is a Microsoft Business Applications MVP focusing on the Power Platform. Interested in learning more about Power Apps Portals? Check out Nick’s Power Apps Portals fundamentals online class.

4 thoughts on “Low-code method to surface data from the Common Data Service (Dynamics 365) on a public webpage. NOT using a Portal.

  1. Awesome, if you use frameworks like HUGO you can even bind to JSON files.. might be easier to update a JSON file than a publish a whole HTML


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s