Modern provisioning in SharePoint has taken on a new framework called Site designs. Site designs are like templates in that they can be used each time a new site is created in your Office 365 tenancy. A site design is essentially a list of actions (site scripts) that you want SharePoint to execute when creating new sites. These actions may include:
- Creating a new list or library (or modifying the default one created with the site)
- Creating site columns, content types, and configuring other list settings
- Applying a theme
- Setting a site logo
- Adding navigation
- Triggering a Microsoft Flow
- Installing a deployed solution from the app catalog
- Setting regional settings for the site
- Setting external sharing capability for the site
Extending site designs
While site designs are continually being improved and expanded on by Microsoft, there are some gaps. From the beginning, Microsoft was aware they wouldn’t be able to fill all gaps from the start so they allowed us to extend the out of the box provisioning using Microsoft Flow and Azure Functions using the “triggerFlow” action. To learn more about this functionality follow this PnP documentation.
This model is extremely extensible and allows you to move some of the workload over to an Azure Function or Azure Automation Services to run PowerShell & C# to apply more custom provisioning artifacts such as pre-configured pages and web parts.
Currently there is a limitation using this model. Given that the provisioning process has moved off into Azure, we are unable to notify the user what the current stage the Azure Function is currently running at.
Here is what the current messaging system looks like
I’ve been told that that ability to provide our own messaging into this dialog is “coming”, but currently I wanted to overcome this limitation.
Clippy is back!
Months ago when SPFx application customizers were released I jokingly built a Clippy extension to run on modern SharePoint pages. The goal was to show how to call Microsoft Graph from an application customizer.
I thought I would supercharge the functionality of Clippy by connecting him to the site design provisioning process.
Socket.io + Express
In order to do this, I had to come up with a mechanism for providing Clippy real-time updates during the provisioning process. I had recently started playing around with Socket.io and I believed this would be the best route forward.
I implemented Socket.io inside an Express api which is currently living up in the Azure. The plan is use this Socket.io as a messaging relay between the Azure Functions and my Clippy extension.
This is what the new flow looks like
We start with a site design that sends the new site URL to Microsoft Flow. Microsoft Flow will pick up that trigger and send an HTTP request to a Durable Azure Function orchestrator in Azure.
The Durable Azure Function orchestrator allows me to split out provisioning tasks (create lists, create pages, provision navigation, apply branding) while at the same time, maintaining state across my Azure Function tasks. As the provisioning is happening, I will send updates to Socket.io.
The Socket.io will receive the message from the Azure Function and update Clippy in real-time in SharePoint.
In order to configure Socket.io to be the messaging system, I had to make sure I was working with individual clients and not broadcasting messages across all Clippy extensions in my tenancy. To do this, I am emitting from Clippy a “room” name. This room is the siteURL of the current site Clippy is running.
By doing this, whenever I send a message from Socket.io to Clippy, I know exactly where to send it to.
Messaging to Clippy is done through a POST request to Socket.Io The POST request contains a message, the provisioning status (complete/running) and the URL (unique identifier for the room). I take these parameters and emit the message to the Clippy extensions where room name is equal to the Site URL.
Configuring Clippy is quite simple, it’s as easy as connecting to Socket.io in Azure and subscribing to the “emit” events.
Inside the _renderPlaceHolders() function of my application customizer, I am going to create a new Clippy and register to Socket.io
Inside the _registerSocketIO, I instantiate a new socket request to Socket.io. Once connected, I am going to send a message with my “room” name. This room name is going to be uniquely identified by the siteUrl of the current site being provisioned.
I have two basic actions I am subscribing to — “provisioningUpdate” and “provisioningComplete”. When Socket.io receives a message and broadcasts that, Clippy will pick it up and “speak” to the user the current update from provisioning.
The Azure Function
As previously mentioned, I am using a Durable Function to do the provisioning process. To learn about Durable Functions follow this link. Here is what the Orchestrator tasks looks like.
Notice that I am passing in the siteUrl coming from my Microsoft Flow HTTP trigger. Inside, I have a couple tasks that are running.
- Establish site as a hub site
- Provisioning Lists
- Provision Pages
- Provision Terms
Also notice that I have an _emitUpdate() function which is running before and after my asynchronous tasks. During the provisioning process, this _emitUpdate is going to POST a message to Socket.io.
What a task looks like
Let’s take a look at what an individual task looks like.
My Azure Function task is going to create a new AppOnly context to SharePoint, load a provisioning template that contains a set of lists to be created and uses ApplyProvisioningTemplate(template) to apply the template to my site.
My _emitUpdate is fairly simple. It’s going to take a message from the Orchestrator, create a new HttpClient and execute a POST message to my Socket.io with the current status of the provisioning process.
Putting it together
Without going to deep into this (because it really is more high level education than anything)… let’s see what these messages look like in real time.
If Gif is missing… wait for it to load. Full size view can be found here.
Want to learn more?
If you are looking to learn more about how I put this together, join me at SharePoint Saturday Denver on October 6th and I’ll be also be demoing this solution at SharePoint Saturday New England! Sign up!