Wednesday, 23 May 2018

Updating your SPFx web part/extension – the nuclear approach

SNAGHTML2356ad3One situation that Office 365 and SharePoint developers will encounter more and more is the need to upgrade an existing SharePoint Framework (SPFx) project to a later version of the framework. SPFx gets updated fairly regularly, and as more and more development moves over to this approach, you’ll find that when you go back to enhance or maintain an existing solution, more frequently it’s SPFx code that you’re going back to. When you do, you have a decision – should you upgrade the SPFx version of the web part/extension while you’re making your code changes? Of course, you don’t have to (and maybe there hasn’t even been a new version of SPFx since your original release). But maybe you want to take advantage of some newer SPFx features – or maybe you just want to stay current and benefit from some possible performance or developer enhancements.

The pains of upgrading a project

Unfortunately, updating an SPFx application is often not as easy as it should be – you’ll often run into build errors when you run a gulp serve or gulp bundle until you’ve got everything straight. Most of the guidance you’ll see advises you to use ‘npm outdated’ to identify packages with newer versions, and then updating them individually (with npm install [package]@[version]) – indeed the SPFx docs have a useful page on this approach at Update SharePoint Framework packages. I recommend always trying this process first. However, I find that sometimes you need some extra steps too. I upgraded a project yesterday and ended up using a slightly different process to get to a working build, so I thought that would be a good topic to briefly discuss.

One issue you can hit with the npm outdated/npm install [package]@[version] approach is if there are new or removed packages which make up the new SPFx version you are moving to. In this case, simply updating your existing packages isn’t enough.

The nuclear approach – a recipe

Sometimes the right thing to do is to be a bit more drastic. You could certainly create an entirely new SPFx application and merge your code into that – but that’s too drastic. It’s a lot of work, and I’ve yet to see a case where it’s actually necessary. The process below is somewhere in between – it’s based on creating a new SPFx project on the latest version, merging the package.json files to ensure you end up with all the right packages at the expected versions and then rebuilding the node_modules folder based on that. I’d use it when:

  • Updating existing packages using npm outdated/npm install@version doesn’t work (still getting build errors)
  • I was confident the previous build is in source control, including a package-lock.json file (so I could revert everything back if needed)

The process would be:

  • Install the latest Yeoman generator version
  • Create a new temporary SPFx app (web part or extension, to match the application you’re updating)
  • Merge the package.json from the temporary app into yours
    • The aim is to have all packages needed – all the SPFx packages for the new framework version, AND any other packages you have previously installed for this web part/extension
  • Remove any package-lock.json or npm-shrinkwrap.json files from local directory (but do not remove from source control - you still might need to go back to a previous build)
  • Delete everything from node_modules
  • Run npm install
  • Make any tweaks to tsconfig.json if needed - newer SPFx versions sometimes need a change here too
    • Build errors should point you to the solution for these. When running an upgrade to SPFx 1.4.1 recently, I needed to add an entry in my “lib” section for “es2015” – but look for build errors for the specific tweak you need
  • Run gulp clean (to delete previous build outputs)

    At this point, you should have a working build again when you run gulp bundle or gulp serve. If you do, and you’re comfortable everything is working, you should:

    • Commit to source control
      • Ensure your package-lock.json file is included – this represents the node_modules tree for this build, and you need it to recreate the build (since you won’t be checking-in the node_modules folder itself)
    • Continue making the code changes you actually came here to do :)

      Other notes

      • Extra care needs to be taken for on-prem SPFx projects. The npm repository holds latest versions of packages, but remember that when you’re on-prem you’re frozen at a certain version of SPFx packages (not what the npm repository holds as the latest version). So, your package.json file needs to reflect the appropriate versions for your on-prem build.

      Good luck!

        Thursday, 10 May 2018

        Licensing for push notifications in PowerApps/Flow

        If you’re doing more with PowerApps and Flow in Office 365, sooner or later you might hit an interesting question if you want to use a premium connector – just who needs the P1 or P2 license? Premium connectors require extra licensing to what comes with Office 365 E1, E3 and even E5, and the licensing requirements can vary depending on the connector and how it is used – meaning costs can vary too. The one I’m focusing on here is push notifications – let’s say you’re building a PowerApp or using a Flow, and you want to send a notification to a mobile device when something happens (i.e. an alert on the device, rather than an e-mail or SMS). In this case, you’ll most likely find your way to the PowerApps push notification action (a premium connector). Whilst there is also a Flow push notification, that one can only send to the Flow owner – but frequently, you want to send the notification to some kind of approver or recipient, not the person who created the Flow. So, the PowerApps Notification is probably what you need – but don’t be fooled by the name. This thing isn’t constrained to use with in a PowerApp (e.g. a button click) - it can also be used within a Flow (e.g. when the Flow gets to a certain stage). Here’s what it looks like there:

        PowerApps notification - in picker


        Who needs the license?

        So the question you get to when you need to notify many people is “who exactly needs a P1/P2 license?”

        • Is it just the user/sender? (which in this case, would be the user who the Flow runs as)?
        • Is it every recipient?
        • Is everyone who could be a recipient?

        It’s an interesting one and I couldn’t find the answer in the documentation. We had the situation come up in some work for a client, so I reached out to a friendly contact in Microsoft (thanks Dan!), and he did some digging internally to find out.

        The answer

        In fact, it depends on how your Flow is triggered – since it can be done by a user action, or indirectly through an event:


        Who needs the license

        License type required

        Manually Any user of the app which triggered the Flow (e.g. your PowerApp, Flow button or other app)
        • Flow is triggered by PowerApp –> PowerApps P1
        • Flow is triggered by Flow button –> Flow P1
        By an event (e.g. new item in a SharePoint list, new file in OneDrive etc.) Just the Flow author
        • P2 (Flow) – * but see my caveat below

        It’s worth being aware that these P1 and P2 additive licenses come in both PowerApps and Flow flavors – but PowerApps licenses always include Flow capabilities. PowerApps licenses are correspondingly more expensive since you unlock the whole, um, power of PowerApps too. Broadly the idea is that:

        • Users creating “basic” PowerApps (e.g. canvas apps) need a P1 license - currently $7 per user per month for PowerApps P1
        • Users creating “advanced” PowerApps (e.g. model-driven apps, business process flows, entities in CDS etc) need a P2 license (currently $40 per user per month for PowerApps P1

        For many PowerApps, that will mean the P1 license is sufficient though (in my view).

          Also note that if you’ll only use Flow and never PowerApps, maybe you just need Flow P1/P2 licenses. These are much cheaper than PowerApps P1/P2 licenses (currently $5 per user per month for Flow P1, $15 per user per month for Flow P2).

          * By the way, with reference to my table above, my understanding is that if you have a PowerApp which adds a SharePoint list item (or file to OneDrive etc.), then a PowerApps license is required for the user – not just a Flow license. After all, the event is really being triggered by the PowerApp – rather than it being a purely indirect thing, from a manually added list item/file for example.

          If you need to know up-to-date pricing, see the PowerApps plans pricing and Flow plans pricing pages. Another good resource (along with licensing examples) is the PowerApps licensing overview page – this has some great info, but it just didn’t have the detail I needed around premium connectors and recipients.

          Other scenarios

          Maybe you want to use the PowerApps push notification purely within PowerApps (i.e. not in Flow). In this case, there are similar considerations:

          • Makers of the app which has the Push Notifications connection need a PowerApps P1 or P2 license (as you’d expect)
          • Users of the app need a PowerApps P1 or P2 license (also as you’d expect, since this is a premium connector remember)

          But there’s an interesting possibility if it’s a different PowerApp which receives the notification (in the PowerApps world, it’s possible for one app to send the notification and another to be receive it). In this case:

          • Users of the recipient app do NOT need a PowerApps P1/P2 license – their Office 365 license is sufficient
            • (This is because this app does not use the Push Notifications connection)

          So, that’s definitely a trick which might be helpful, so long as the implementation details are OK with your requirements (i.e. you are able to split your app in this way).


          There are definitely a few complexities around licensing of PowerApps and Flow, and as you build more solutions with them there are more scenarios to consider – in fact, . I’m really not trying to be the man to answer all your licensing questions here though :) You’ll need to contact Microsoft if the above links don’t have the detailed information you need, as they’ll give a better answer than I ever could. However, I thought some folks might run into the same questions that I did, and I figured some of this info needs more prominence.

          Have fun building your solutions!

          Wednesday, 4 April 2018

          Control Office 365 Group creation – a simple no-code solution

          In the Microsoft view of the world, every user in an organization using Office 365 should be able to create Groups – and remember that they can be created from Outlook, Microsoft Teams, Planner, Power BI, SharePoint and so on. However, in the real world it seems there are few large enterprises willing to go with that. Personally I’m not surprised. I think there are many reasons to introduce more governance – perhaps you want to collect some metadata about the requestor/group/business unit/division, or perhaps you just want an admin to check this is a genuine/justified request. Or maybe you want to check if a SharePoint site already exists for this, because you’ll do something different if it does (e.g. “Groupify” that site instead). Of course, it’s possible to lock down Group creation to a central admin team using the "GroupCreationAllowedGroupId" approach (see Manage who can create Office 365 Groups) - however, unless you supplement this with something else (such as have users raise a support ticket when they need a new group) you have no real user-facing “request process”.

          So what if we could have a really simple no-code solution using purely out-of-the-box things in Office 365, based on a simple SharePoint list which we could point users to, with Microsoft Flow providing the approval steps to get the control we need?

          Of course, you might not care too much about the concept of Office 365 Groups itself. But you might care about providing Microsoft Teams or SharePoint sites to the business, or one of the other more functional things built on top of Groups. The solution outlined here may become even more valuable when Office 365 allows a Team to be provisioned alongside a Group – we’re currently waiting for APIs around this, but it’s on the way soon. So, consider the solution outlined here to be a Teams provisioning solution in the future, not just the Groups provisioning solution it currently is.

          In implementation terms, I’ve seen many articles showing slightly different ways of provisioning Groups and sites in Office 365, but nearly all use some custom code e.g. an Azure Function. One of the nicer ones is Martina Grom’s series starting here, but I was wondering if there was a simpler approach. Azure Functions are great of course (I’m giving a talk on them at the European Collaboration Summit 2018 in Germany soon) – but unless the organization is already using Azure for code hosting, it can introduce some barriers. This is because an Azure subscription is suddenly needed, someone is asking about forecast costs (even though us devs know they are low on a consumption plan), someone needs to sign-off and so on. Or, you might just prefer a no-code solution for other reasons. So..

          Implementing controlled Group provisioning with a SharePoint list, a Flow, and the Graph

          The ingredients for this solution are:

          • A SharePoint list
          • A Flow (with just a few actions)
          • An Azure AD app registration (to allow calling the Graph)

          Yes, we do need to do *something* in Azure. We need to register an application and grant it permissions to create Groups and add users to them. But you don’t need any pay-for Azure for this, since Azure Active Directory is bundled with Office 365 and you’re just registering an application there so that your Flow can call the Graph. As we said before, there’s no code running anywhere – so no Azure Functions, queues, databases, storage or anything like that.

          Our completed Flow looks like this:

          Group creation Flow

          As you can see, there are a couple of extras beyond simply creating the Group, which I think you would want in the real world:

          • Groups get added to a separate “Created Groups” list – otherwise, our ‘requests’ list wouldn’t help us understand if any Groups actually failed to create and don’t exist. In the Created Groups list, we add the Group ID (which might be useful to administrators), and you could easily extend this to add other data
          • We add the person who requested the Group to be Group owner – otherwise, he/she doesn’t have permission! This is something of a gotcha, since you’d either need I.T. to do a manual step for each one (which kind of defeats the purpose of an automated Group provisioning system).
            • N.B. there is some complexity to this in Flow, and that’s what the latter steps of the Flow are all about – parsing some JSON to obtain the ID of the created Group and the user who requested the Group, and then making a separate call to the Graph to add this user as Group owner. But still, it *can* be done without code.
          Approval step

          NOTE – one thing I’m excluding in my Flow/the details in this article is the actual approval step which gives you the control. This is an exercise for the implementer, since it’s trivial to implement in Flow and everyone’s requirements might be a little different (e.g. one-level/two level approval, different recipients etc.). This is typically done with the “Start an approval” step in Flow.

          The key – calling the Graph with Flow’s HTTP action

          As I showed in 5 ideas for using Flow in your applications, it’s possible to easily create an Office 365 Group (or do MANY things around users, mail, calendar, files and so on in Office 365) by having your Flow call the Microsoft Graph. For many developers, this is simpler than code because there is none of the complexity around obtaining an authentication token (which varies depending on where you are calling from). The simple HTTP action in Flow can be used for this:


          This works because it has a way of providing authentication details to the specified endpoint – to be precise, we use the Client ID and Client Secret of our AAD app registration. This is one way of authenticating with the Graph (known as the OAuth “Client Credentials” grant), which itself works from code, a Flow, or anything else which can call over HTTP. The config steps are simple. But let’s start with the SharePoint list..

          Step 1 – create a SharePoint list for Group requests

          All that’s needed here is a simple list for users to visit when they need a new workspace for their team. Add columns for:

          • Group short name
          • Group display name
          • Group description

          N.B. You could combine the ‘Title’ field of the list with the Group display name or similar – I kept them separate (to perhaps use the Title for some other descriptive text), but up to you. So my list looks like:


          ..and then the form looks like this:


          OPTIONAL – create a 2nd SharePoint list named something like “Created Groups” to track successfully created Groups. The steps I provide later to configure the Flow are based on this approach – I simply add a field for “Group ID”, although you could extend this to include the URL, owner and whatever other fields are useful:


          Step 2 – configure an Azure AD app registration

          The other thing we need is an AAD app registration. You’ll need permissions in Azure to do this, but the following screens walk you through:


          In the next screen, the sign-on URL can be anything you like when being used with Flow – just use something logical:


          Then go into the Settings for the App Registration, and select ‘Required permissions’:


          Click ‘Add’, and then select ‘Microsoft Graph’.

          In the next screen that appears, find the ‘APPLICATION PERMISSIONS’ area and in that section, select the following:


          Click ‘Done’ to complete.

          You’ll also need to ensure the user that the Flow runs as has consented to the permissions. The simplest way to do this is actually grant permissions to all users in the tenant, since this can be done easily with the Grant Permissions button:


          Otherwise you need to write some code which uses this AAD registration and can prompt the user to consent (in a browser session logged in as the user who owns the Flow). In this case, you might legitimately decide that the permissions that this app has are not too far-reaching, and applying the consent to all users is fine. 

          Step 3 – implementing the Flow

          OK, so let’s move to the main config step – configuring the Flow. There are two ways you could do this:

          • Import the Flow that I’m providing at the link below, and reconfigure a couple of things
          • Create the Flow yourself, and configure the same actions – I provide some info in the table below if you choose this route
          Option 1 – import the Flow I provide:

          You can download my Flow from this link:


          To import, go into the Flow area in Office 365 by finding the Flow icon in the app launcher. Once in there, you should see an option to import:


          You’ll need to do the following once the Flow has imported:

          1. Define a new SharePoint connection (or use an existing one) so that the Flow can connect to your SharePoint lists
          2. Edit Flow – overwrite the following settings:
            1. Edit all the HTTP actions (the green ones) – for each, enter YOUR AAD app registration details:
              1. Tenant (this is also known as the Directory ID of the AAD directory you’re working with – you can get this from the Azure portal, in the “Properties” area for your Azure Active Directory)
              2. Client ID
              3. Secret
            2. Edit the “When an item is created in Group Requests list” action – for this, you need to select the “Group Requests” SharePoint list you created earlier. There’s a slightly non-obvious thing here – you need to select “Enter Custom Value” from the dropdown, and you will then be allowed to type/paste in the the site URL where your list is. Once this is done, the 2nd dropdown should display all the lists in the site, and you can pick the right one
          3. Save the Flow
          4. Test!
          Option 2 – create your own Flow, and configure the right actions:

          If you prefer to create the Flow yourself, you’ll need to go to the “Group Requests” SharePoint list you created first. Click the “Flows” button on the command bar, then create a new Flow. Select the “when an item has been added” option. Here’s a high-level view of the actions to add to the Flow:

          Action to add Purpose/name Steps you need to take
          HTTP Create Office 365 Group (team space)

          In this action, you’re making a POST request to the following Graph endpoint:


          Reference the Create Group documentation in the Graph to understand the headers and body to pass. Make sure to drop in variables for the values for the mailNickname, displayName and description of the Group.

          Also specify details for your AAD app registration:

          - Tenant ID

          - Client ID

          - Secret

          Parse JSON Parse JSON (created Group details)

          Parse response body from previous action - the purpose is to get the ID of the Group that was just created (so that we can add a Group owner later, and also to log the Group ID to the “Created Groups” list).

          Paste the following into the ‘Schema’ box:


          "type": "object",

          "properties": {

          "id": {

          "type": "string"


          "description": {

          "type": [





          "displayName": {

          "type": [





          "groupTypes": {

          "type": "array",

          "items": {

          "type": "string"



          "mail": {

          "type": "string"


          "mailEnabled": {

          "type": "boolean"


          "mailNickname": {

          "type": "string"


          "securityEnabled": {

          "type": "boolean"




          SharePoint - add item to list Add item to Created Groups list

          Add an item to the other list (“Created Groups”) to log that the Group was created. Once you have selected the site, you should be able to select the list and reference columns.

          Drop in variables from the previous “parse JSON” action to obtain the Group ID and display name.

          HTTP Get user

          In this action you’re making a GET request to the following Graph endpoint:


          Reference the Get User documentation to understand how to call, but this one is simpler since no body or headers are required.

          Make sure to drop in the variable for the UserID at the end of the URL – you’ll need the ID or UPN of the user. If your e-mail addresses are the same as UPNs, you can use the “Created by e-mail” variable from the first action in the flow (when a new item is added to the “Requested Groups” list).

          Also specify details for your AAD app registration:

          - Tenant ID

          - Client ID

          - Secret

          Parse JSON Parse JSON (Group requester)

          Parse response body from previous action - the purpose is to get the user ID (in AAD) of the Group requester, so that we can add this user as a Group owner.

          Paste the following into the ‘Schema’ box:


          "type": "object",

          "properties": {

          "businessPhones": {

          "type": "array",

          "items": {

          "type": [






          "userPrincipalName": {

          "type": "string"


          "id": {

          "type": "string"




          HTTP Add owner to created Group

          In this action, you’re making a POST request to the following Graph endpoint:

[Group ID]/owners/$ref

          Reference the Add Group Owner documentation in the Graph to understand the headers and body to pass. Note that you need the Group ID in the URL, and the User ID to be passed in the body of the request – drop in variables from earlier actions as appropriate.

          Also specify details for your AAD app registration:

          - Tenant ID

          - Client ID

          - Secret


          With the right combination of calls to the Graph and parsing the responses returned, it’s possible to create new Office 365 Groups and (add the requesting user as the owner) purely through Flow, with no need for custom code such as an Azure Function. Since Flow has great support for approvals, it’s easy to add whatever approval steps you need to get the control which is right for your organization – and approvers can approve/reject directly from the e-mail they receive, the Flow app on their phone or tablet, or the Flow approvals center. Perhaps some items in my 5 ideas for using Flow in your applications article could also be useful in helping you build out a really nice Group provisioning process – in some cases you might want to put a lot more effort in (e.g. to produce a custom form and user experience), but if you want something at the simpler end, the approach described here might be helpful. And if you do need a richer solution, perhaps consider that this Flow/Graph approach to provisioning Groups could be dropped in as the core mechanism in something bigger too. Good luck!

          Sunday, 4 March 2018

          5 ideas for using Flow in your applications

          Like many others, my team and I have been doing more and more with Microsoft Flow recently. It’s true that it does have some limitations, especially when you get into longer running processes which are more “state machine” than “take this set of actions” (or you want to understand more around update of items in SharePoint, or respond to delete events, rather than new), but overall the capabilities are incredible. In particular, it’s the connectors to other services that make Flow – and the resulting set of things you can do with them. Chatting to some other developers recently, it occurred to me that lots of Office 365 technical people are probably unaware of what Flow can do these days - and so that motivated this article. My list of cool things you can do for this article is:

          • Send a message on Skype for Business
          • Post into a Microsoft Team
          • Add a row to Excel
          • Create an Office 365 Group (via a call to the Graph)
          • Send a push notification to a mobile device

          A few days earlier, I found myself doing strange things in a Flow I was building – I just needed to do some basic debugging to find out why my process was going down one branch, when I expected to be going down another. Why was the value I was testing in my “if/else” condition not what I was expecting? I figured I would add some quick and dirty logging somewhere so I could get better visibility of things (and probably remove or change this later) – but then I couldn’t find something logical to log with. My initial thought was to use Azure Application Insights – I recently talked about using this in intranets and page widgets to track events in your code i.e. particular actions that users take. How often is your app launched? How often are users clicking that special button? How many users ever switch to the second tab of your user interface? Or, perhaps in site provisioning – how many sites are being requested, and how long do things take? I figured that you could log to App Insights at particular points of your Flow, and that would be a great way of analyzing the most common path through a Flow, or perhaps doing some debugging during the build.

          Unfortunately, there is no “Track event in Azure App Insights” action yet :(

          I added a UserVoice item here if you also think this would be a good thing and feel like voting.

          Anyway, this led me to having some fun with other possibilities – you could use them for quick and dirty debugging like me, but I think there are a lot of true business possibilities here and so it’s worth being aware of them.

          Send a message on Skype for Business

          This one could be useful if a person/team needs to be notified *immediately* when something is added or changes somewhere in Office 365, and for some reason an e-mail notification isn’t a good fit. Arguably this one works best if the recipient is a desktop/PC user – later I talk about options for notifications to mobile workers. Anyway, it certainly gets the user’s attention, and it can be configured in your Flow very quickly. Here’s the end-user experience:



          Here’s what it looks like in Flow:


          Post a message to a Microsoft Team

          But enough of Skype for Business, the future for most organizations (in the Microsoft cloud) is Teams of course. As you’d expect, there’s good integration between Flow and Teams. Saying that, it’s not currently possible to send a chat message in Microsoft Teams, but we can post to a channel – which is arguably more useful in the real world. Here’s what it looks like in Teams:


          Here’s what it looks like in Flow:


          Add a row to Excel

          Of course, half of the world’s critical processes are still running in Excel. Fortunately, you can easily use Excel as a data source from Flow, whether that means reading from or writing to workbooks – it’s trivial if the Excel file is somewhere in Office 365. In the example below, I’m adding a row to an Excel workbook every time an expense report is submitted to SharePoint. This could be used by a finance team for reporting or to help with some month-end processes perhaps. The end result is an Excel spreadsheet which is being built up automatically over time, and I can pull details from the SharePoint item into Excel:


          Here’s what it looks like in Flow:




          HTTP call to the Graph (with AAD auth) – e.g. to create an Office 365 Group

          Some really interesting possibilities come with calling the Microsoft Graph from Flow. Obviously the Graph is the gateway to all things related to mail, calendar events, contacts, documents in SharePoint/OneDrive, Planner tasks, Teams and more. In this case I’m focusing on Office 365 Groups. How about a way to control Group requests and creation through a SharePoint list with approval? I implemented this in 20 minutes flat, and I think many organizations in Office 365 would get a lot of bang for buck from such a process. The ingredients are:

          • A SharePoint list for users to request a new Office 365 Group – this provides the form
          • A Flow with a ‘Start an Approval’ action – this provides the controlled creation/approval by an administrator step
          • A HTTP action added to the Flow (when it goes down the “approved” condition branch) – this calls the Graph, in this case, a POST to the /Groups endpoint with the details of the Group to be created
            • An AAD app registration for to authenticate with the Graph – this must have permissions to create Groups (e.g. Group.ReadWrite.All)

          So, if you imagine a SharePoint list where items get added:


          We add a Flow to respond when a new item is added to the list, and somewhere in there we add the simple HTTP action (e.g. after an approval step):


          We configure this to point to the correct URL in the Graph API, and pass the appropriate JSON for Group creation:


          There’s actually a bit more to it than that – we need to specify authentication details for the call, in this case specifying the Client ID and Secret for our AAD app registration which has the appropriate permissions (done separately in the Azure portal):


          ..and then, when an item is added to the list and it is approved by an admin, the Group is created along with the corresponding mailbox, calendar, SharePoint site and so on:



          Not bad for 20 minutes work! Of course, the ability to easily call the Graph means you could do a bunch of things – I can certainly imagine lots of business processes where it would be useful to do things like:

          • Create a calendar item
          • Create a task in Planner
          • Update a user profile
          • Add a new contact

          ..and so on. A quick look at the Graph documentation should give you lots of ideas.

          Send a push notification to the Flow owner on their mobile device

          What if you need to get an immediate notification out to some users or administrators who are typically mobile or out in the field when something is changed in Office 365, and e-mail or SMS aren’t the right solution? We’re used to getting push notifications from certain apps on our phone/tablet these days, but developing a custom app and getting this in the hands of all your users can be expensive and time-consuming. If you can get the iOS/Android versions of the PowerApps or Flow mobile apps in their hands instead – and remember, users can install those right now from the respective app stores – then you can send push notifications to these apps very easily.


          OK, so there are some caveats with this one, partly because there are two ways you can send push notifications. The caveats are:

          • The standard Flow push notification can only send *to the Flow owner*
          • The PowerApps push notification can send to anyone, but your app users need to be on a premium (paid) plan – remember this doesn’t necessarily need to be everyone in the org though

          It’s also worth considering that if you need a notification that something needs to be approved by the recipient, Flow can do something even better for that – Flow approvals work great in the Flow mobile app. The task details are shown fairly clearly, with big “Approve” and “Reject” buttons:


          Nothing special is needed for this, just regular use of the Flow ‘Start an Approval’ action. If the recipient has the Flow app installed on their device and is logged-in, they’ll receive the notification and be able to approve/reject extremely easily from inside the app.

          But what about other types of notifications? Perhaps someone has submitted something, and you need to confirm to them that it has been logged and a process has been started? Well, if you can use the PowerApps push notification option, this works great and you can even prompt the user to open your PowerApp (and pass parameters to load a particular item/take the user to a particular screen etc.):


          When the user opens the notification, your particular PowerApp can open. Here’s what it looks like in Flow:


          Pretty nice stuff really.


          I think it’s a good idea for all developers, architects and technical business folks working in Office 365 to be aware of the possibilities of Microsoft Flow. There’s a significant leap forward here in terms of what can be accomplished for the amount of effort involved – and so many organizational processes can benefit from this stuff. I’ve presented 5 ideas here of some things that might be useful, but I’m focusing mainly on taking other actions in or communicating via Office 365. Consider also that Flow has a LONG list of connectors to 3rd party applications – and although all the top enterprise productivity vendors have a similar list, I don’t believe anyone is taking it as far as Microsoft are. The image below shows a small selection (just those starting with letters P to W!):


          Even in this set you can see Salesforce, ServiceNow, WorkDay and lots of other enterprise systems.

          I think some of this stuff is killer for Office 365 personally. Happy process building!

            Thursday, 15 February 2018

            PowerApps – implementing offline support in your app

            In the previous article I talked about my views on the good, the bad and the ugly of PowerApps at the present time (early 2018), but today I want to focus on a particular scenario – ensuring your app can be used offline. Not all apps will require this capability, but for some scenarios it will be vital. Unfortunately there is no magic button when building the PowerApp which makes it support offline – the implementer has to build it in his/herself, and this can make a simple app quite a bit more complication.

            When we talk about an app working when offline, I’d say the general expectation is that:

            • The app is usable (e.g. any dropdowns which pull data from somewhere continue to work)
            • If the app is focused on writing data to somewhere (e.g. a SharePoint list/database/Excel file stored somewhere online etc.), then it should be possible to submit the record whilst offline – even if the connection needs to be resumed for it to actually be saved to the back-end
              • I think lots of PowerApps fall into this category (e.g. log a new incident/I.T. request/holiday request/expense claim etc.), so I’m going to focus on this aspect today
            • If the app reads existing data (e.g. show existing incidents/requests), then it should be possible to access at least some of this data offline (e.g. most recent 20 records, say)

            The PowerApps blog has some good info in Build offline apps with new PowerApps capabilities, but I found myself doing some things differently – so thought it worth discussing here.

              Understanding the deal with offline

                A big thing to recognize here is that *the app must be opened for a while once the connection is resumed for data to be submitted*. It’s not like the “fire and forget” experience with the e-mail application on your phone (and one or two other native or “tier 1” applications), where you can hit send and trust the data to be sent even if your phone stays in your pocket. Instead, your users need to have your PowerApp open for a while – and the specifics depend on how you implement offline. In my case I used a timer which checks every 5 seconds if the device is connected to the internet, and then saves the record to SharePoint Online if so – this means the user doesn’t have to DO anything in the app (e.g. press a button), which is something. And, of course, as these things are happening in the background it’s important to communicate the status to the user, so it’s clear when their record has been saved to the back-end.

                By the way, this deal isn’t specific to PowerApps. I’m no expert here, but it seems nearly all 3rd party app (including other apps you might use for such a use case e.g. Nintex Mobile) require this due to constraints on the background processing apps can do when not in use. Even with the right settings in place on your device (e.g. “Background App Refresh” enabled on iOS), this isn’t enough for these apps to push data it seems. So, prepare to coach your users in having the app open for a while once re-connected – and as I show below, you could consider making this really clear in the user experience.

                A sample experience (from my POC app)

                Here’s a video of offline support in an app I built recently, recorded from my iPhone – the holiday/leave requests app I mentioned in the last post. This simulates a user submitting a leave request without a connection (flight mode enabled), and then the record actually being saved to SharePoint Online once the connection is back (flight mode disabled):

                The recipe for offline in PowerApps

                In this section I’ll go through the different bits which are making the offline behaviour work, and provide some starter PowerApps formulas where appropriate (with the important functions highlighted). Remember my case focuses only on adding a new item to a SharePoint list, so it’s the PATCH function which is doing this work. Overall, the recipe I used was:

                • Two info screens within the app:
                  • Pending screen
                  • Confirmation screen
                • Formula behind submit button:
                  • If connected, PATCH record to SharePoint
                  • If not connected, CLEARCOLLECT to save record locally
                  • RESET form (to clear existing values)
                  • NAVIGATE to pending screen

                    If(Connection.Connected, Patch('My SharePoint list', Defaults('My SharePoint list'), {Title:Concatenate("Leave Request - ", User().Email, " - ", Text(Now(), "[$-en-GB]dd/mm/yyyy hh:mm:ss" )),SomeField1:SomeControl1.Value, SomeTextField1.SomeTextControl1.Text,SomeChoiceField: {    '@odata.type':"#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference", Value: SomeDropDownListControl.Selected.Value, Id: 1 });
                    Navigate(ConfirmationScreen, ScreenTransition.Fade),
                    ClearCollect(LocalRecord, {Title:Concatenate("Leave Request - ", User().Email, " - ", Text(Now(), "[$-en-GB]dd/mm/yyyy hh:mm:ss" )),SomeField1:SomeControl1.Value, SomeTextField1.SomeTextControl1.Text,SomeChoiceField: {    '@odata.type':"#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference", Value: SomeDropDownListControl.Selected.Value, Id: 1 });
                    Navigate(PendingScreen, ScreenTransition.Fade))
                • Formula for Timer control (implemented on both “start” and “pending” screens – so user can have app open in any logical location, and record will be submitted). In the OnEnd event:
                  • If connected and have record(s) in “LocalRecord”, iterate each record with FORALL and then PATCH to SharePoint
                  • NAVIGATE to confirmation screen
                  • CLEAR “LocalRecord”

                    If(Connection.Connected,ForAll(LocalRecord, Patch('My SharePoint list', Defaults('My SharePoint list'), {Title:Concatenate("Leave Request - ", User().Email, " - ", Text(Now(), "[$-en-GB]dd/mm/yyyy hh:mm:ss" )),SomeField1:SomeControl1.Value, SomeTextField1.SomeTextControl1.Text,SomeChoiceField: {    '@odata.type':"#Microsoft.Azure.Connectors.SharePoint.SPListExpandedReference", Value: SomeDropDownListControl.Selected.Value, Id: 1 }});
                    Navigate(ConfirmationScreen, ScreenTransition.Fade));

                • A “status bar” within the app indicating whether the device is connected or not (as a simple reminder to the user)

                WARNING – those formula extracts are edited/simplified versions of my real ones, and maybe the closing brackets aren’t exactly right. Take care if you try to use them for your formulas – really I’m just trying to convey the concepts!

                  Dealing with reading from data sources when offline (e.g. for dropdowns)

                  One thing to look out for is if your SharePoint list has choice or lookup fields – you might be presenting the options in a dropdown list or with radio buttons in your app. Since November 2017, you can now have multi-select on such fields, but unfortunately if the user happens to use your app for the first time in offline mode, the dropdown list will not be populated (it will display “Find items”, but no list appears when the user clicks). The user can type in an option, but since they are not selecting from a list of valid choices this will generally go horribly wrong and the item will not be added to SharePoint.

                  Also consider that you are most likely not using taxonomy/managed metadata fields, because they are still read-only (as at February 2018).

                  So, you need to work around this. One option, especially if you’re already using the PATCH command or similar to update SharePoint, is to bind your control to some static data which can be accessed offline. This is a bit lame, as you’re essentially duplicating the items as hardcoded data within your app – you lose the benefits of your choice/lookup field, i.e. the form dynamically fetching the right options based on what is defined in SharePoint. You could probably do something clever with a formula which refreshes a collection when the app has a connection, but it would be nice if this was handled in a better way by the PowerApps infrastructure. Maybe in the future :)


                  PowerApps can work just great offline, but it’s all down to the implementer. The PowerApps framework provides the ability to detect if the device currently has a connection, a timer control (so that actions can be taken automatically), and the various functions for adding/updating data in a data source (e.g. PATCH, UPDATE etc.). These are the ingredients to use when implementing offline support in your app – there’s work to do, but you can control the experience and make sure it makes sense in your context.

                  Further reading -

                  Tuesday, 6 February 2018

                  PowerApps–the good, the bad and the ugly (early 2018)

                  I’ve been doing quite a lot of work with PowerApps for clients recently, and it’s been an interesting time. No doubt I’m still not the world’s most capable PowerApps implementer by any stretch of the imagination, but I feel like I’ve been through the usual denial/anger/acceptance phases that often come with a new technology ;) Some of my work has centred on a proof-of-concept application for one of the big airlines – specifically, building an app that pilots should be able to use whilst offline on an iPad. The project was to digitise some forms related to booking leave, which is an important part of flight crew scheduling. We effectively rolled 3 forms into one app:


                  I gave a presentation on this recently to my colleagues at Content and Code, but I’ve also genericised some of the information so it can be shared more widely (Contoso Airlines!). The deck shared below is a combination of some typical lessons learnt and tips, but also has my thoughts on where PowerApps is a technology, structured into “the good, the bad and the ugly”.

                  Potentially transformative, but with a learning curve..

                  My conclusions are that it’s a great technology and although it’s aimed at forms-type applications in general, it really shines for relatively simple mobile apps. The organization just has to deal with getting users to have the PowerApps app installed (either from the app store, via an MDM solution such as Intune or Airwatch, or another approach) and then all the PowerApps forms and applications the organization provides will show up there. This is *far* easier and cheaper than developing individual native apps on iOS and Android, which each need to be distributed to users once the build is complete. In contrast, it’s feasible that you could have your Office 365 users working with a simple PowerApp on their mobile device within hours. Think about that for a moment! Sure, PowerApps doesn’t give you the richness that a high-end native app can have, but the barrier to entry is much lower.

                  However, it’s not always the simplest for the app implementer to work with. Frequently, things can get into a territory that I’d argue most power users would struggle with. An example in my case was having to abandon the default SharePoint integration/data-handling, and craft my own formulas which use the Patch() function to add an item to a SharePoint list (necessary because my form used multiple screens). This is fiddly work if you have lots of form fields and columns in the underlying list, even for a developer used to such things.

                  Customizing SharePoint lists vs. creating a standalone PowerApp

                  The implementer must choose between two approaches – customizing the form of a SharePoint list, or creating a “standalone” PowerApp (which might talk to the very same list). Conceptually these are quite different, and have different behaviours. This decision is expressed in the PowerApps menu on a SharePoint list:


                  A key thing here is that customized SharePoint forms do not show up in the PowerApps app:


                  If users need to work with a customized SharePoint list on their mobile device, then using the SharePoint mobile app instead provides a reasonable experience – in fact, the SharePoint app should hand-off to the PowerApps app when you go to the list, and the customized PowerApps form should then be loaded. However, this currently seems to be a bit hit and miss – most often, I actually just get a web rendered view of the PowerApp, and here it seems that the experience isn’t as optimized for mobile as a true PowerApp – some pinching/zooming is often necessary.

                  I’m sure things will be straightened out here eventually, but I still think I’d prefer a different model – what about if certain customized SharePoint lists could be flagged to appear within the PowerApps app (perhaps by a tenant administrator)? That would seem a better arrangement to me at least.. 

                  Other interesting aspects

                  The presentation includes some high-level detail on other things I’ve worked with that might be interesting:

                  • Installing the on-premises Data Gateway to connect to on-premises data (SQL Server in my case)
                  • Implementing offline support in a PowerApp (using a Timer control to submit data once reconnected)
                  • Some implementation details around using a Gallery control for navigation, and the 10 PowerApps functions I found most useful from the 150+ functions which are available

                  My “good, bad and ugly” summary:

                  If you’re not that interested in the presentation and want to skip straight to the summary, here are my conclusion slides:




                  By the way, if you’re wondering what I mean by “web experience (upscaled phone/tablet view)”, let me try to explain. Certainly a form/app looks good on a mobile device, and is optimized for that form factor – all the controls are very “thumb-able”, and even typing into a textbox works fine (shown here at tablet/iPad size):

                  4 - BA PowerApp - paternity leave screen

                  But when a PowerApp is accessed on a PC, there is no responsive design or optimization for the device – the very same rendering for phone/tablet is used, which is just plain weird in my view:

                  PowerApps - PC 800 - msg

                  And no, I don’t know the Office 365 suite bar displays “Dynamics 365” either (particularly since Dynamics is not even in use in this tenant). But I’d happily live with that if I could have a better experience than the strange “phone screen in a PC browser” deal that we currently get. Nintex Forms does a better job of this, so I’m not sure why PowerApps went down this route. Again, I’m hopeful some enhancements to this will appear at some point.

                  So that's some headlines from what I spoke about. I'll most likely publish some other PowerApps articles which dive into more detail on implementing offline/using the on-premises Data Gateway etc., but essentially I just wanted to share the slide deck in case it’s useful to anyone:

                  The slide deck:

                  Thursday, 4 January 2018

                  Using Site Designs or PnP templates for SharePoint site provisioning

                  So the new “site designs and site scripts” capability for creating SharePoint sites from a template is starting to become available in Office 365. This provides an alternative approach to using Microsoft’s Patterns and Practices (PnP) provisioning library and XML, which has been the way that most experienced implementers have been creating custom site templates in recent times. For a full “self-service” implementation, it’s typical to provide a custom form for end-users to request sites and provide any required information - the PnP building blocks provide support this, although some tailoring is needed in most cases plus the work to implement in the organization’s Office 365 and Azure environment. Microsoft are introducing site designs/site scripts as an alternative way of templating SharePoint sites, which is more baked-in to Office 365.

                  However, it’s not just a simple “either/or” decision between site designs and PnP – both are valid approaches, and there are quite a few considerations which could lead you to use one or the other. In addition, it’s also possible to combine both approaches by calling a PnP template *from* a site design. This is very welcome since:

                  • there are lots of tweaks to a SharePoint site that are not possible yet with site designs
                  • lots of organizations have an existing investment in custom site templates implemented with PnP

                  So, the implementer can choose between site designs, PnP provisioning, or a combination of the two. In this post I’d like to explore some of the factors around your SharePoint site creation/templating strategy.

                  Key considerations for Site Designs

                  1. End-users create sites directly (with no approval step)

                  Site designs that you define become available for selection in the out-of-the-box site creation experience. There is no approval process, and in general you have to be happy with the user experience which is provided. It’s the "SharePoint home" page where the site creation UI is surfaced - accessed from the 'SharePoint' text in the Office 365 header or the 'SharePoint' app in the app launcher. Self-service site creation must be enabled on the tenant for the 'Create site' link to show (SharePoint Admin Center > Settings > Site Creation > “Show the Create site command to users who have permission to create sites”). Note that it is possible to restrict the use of specific site designs to certain groups of people (e.g. if you had a template for an 'executive site' or a 'finance site', and only certain groups of people should see this option) with commands such as Grant-SPOSiteDesignRights or GrantSiteDesignRights (REST), but the top-level switch which enables all users to create sites must be enabled on the tenant – those commands only hide/show specific templates.  

                  Here’s what the experience looks like:

                  COB site design - create site

                  COB site design - site design selection

                  COB site design - form 1

                  COB site design - form 2 

                  2. It’s possible to provide a custom form, but implementation effort is needed (especially to collect custom metadata)

                  As users create sites, it’s common to want to collect some custom metadata – things like business unit, purpose, cost centre and so on. Happily, it appears possible to provide a custom form to facilitate this (but it’s not working yet in any of my tenants):

                  Custom site creation form

                  It’s not yet clear what form (ahem) the form is expected in. It could be that a PowerApp form is expected here, in which case we’d be specifying something like:

                  Custom site creation form - PowerApps

                  However, in addition to implementation effort required to develop and host the custom form, I envisage that a chunk of work is required for that custom metadata to be applied somewhere. After all, you’ll need to decide whether this gets stored somewhere in the site (e.g. property bag) or in some centralized list or database somewhere. So as an accompanying point, it’s perhaps worth remembering that…

                  2.5 There is no site directory “list”, except for your site collection list in the SharePoint Admin Center

                  In a typical SharePoint site templating implementation (based on PnP or not), there’s usually a SharePoint list which contains details of all the sites which have been requested and created. Often the implementer will store custom metadata (such as division, cost centre etc.) in this list, particularly if doesn’t need to be updated by the site owner on an ongoing basis. But there’s no such list with the native site creation setup, only your list of site collections in the SharePoint Admin Center - and remember these Group sites will only show in the NEW Admin Center due to be launched in early 2018! It’s not yet clear whether this will support custom metadata and make the whole thing easy, but I doubt it – I’d fully expect there to be work to do to handle your custom metadata, and I think that’s fair..

                    3. Cannot block ability to create communication sites

                    Some organizations are happy for end-users to create team sites from approved templates, but want communication sites to be a more controlled thing – perhaps because they’re worried some folks will take communication sites too far and create lots of mini-intranets. Unfortunately this isn’t possible currently. If end users can create SharePoint sites (the default), they can create both team sites and communication sites. Certainly, communication sites are a welcome addition to SharePoint Online - but I could believe some organizations will block the out-of-the-box site creation tools and implement their own version with more governance for this reason.

                    The first step of creating a site using the out-of-the-box UI is shown below (but not in the series above) – as you can see, both types are available for selection:

                    COB site design - site type

                    4. Site designs create Office 365 Group sites (unless you have disabled the ability for end-users to create Groups)

                    As you might know, when a site is created from the SharePoint home page (as shown above) it’s actually an Office 365 Group which is created – assuming that is, that your Office 365 environment is using the default setting which allows all end users to create Groups. If not, a classic/standalone SharePoint site is created. All this is the case whether a custom site design is applied or not. With a Group of course, a bunch of things are actually being provisioned not just a SharePoint site collection – including a shared mailbox for group conversations, a calendar, a Planner Plan and so on. This is perfect if your collaboration strategy is based on Office 365 Groups – but this requires detailed consideration. Organizations should not wander into this blindly.

                    ..but a Team is not automatically created for the Group..

                    Notably a Microsoft Team is not provisioned for the Group – similar to if the Group was created from Outlook, Yammer, Power BI or one of the other endpoints. But it is possible to easily add a Team as a separate step if needed. Any user who has permissions to create a Team will see something this option when they go to create a Team:

                    COB create new team - 1

                    COB create new team - 2

                    In all this, you should be considering whether your strategy is based on Office 365 Groups which can be created by any user (the default), or whether you prefer to do something else. This is a fairly big topic, but there are several options here, including:

                    • Provide a means for end-users to create (or simply request) SharePoint sites which are not Groups i.e. they are classic standalone SharePoint site collections
                    • Restrict who can create Groups in the organization, by using the Set-AzureADDirectorySetting command with the "GroupCreationAllowedGroupId" parameter to restrict Group creation to members of a special group (e.g. I.T. staff) – see Manage who can create Office 365 Groups for more info
                      • (N.B. Microsoft recently clarified the licensing requirements around enabling this option – users who ARE able to create Groups must have an Azure AD Premium license, but the rest of the organization does not)
                    • Both of the above
                    • Don’t use Groups at all
                    • Provide a means for end-users to create (or simply request) a site which is an Office 365 Group, but using a custom form as described earlier or an entirely custom interface (e.g. because you have particular requirements not satisfied by the out-of-the-box UI)

                    Overall, you can’t really get into site designs for team sites without considering wider aspects of collaboration. Oh and remember, if you provide site designs for communication sites (rather than team sites), those are NOT Group-connected sites. By the way I think Microsoft made the right call there, given the nature of most communication sites..

                    5. Using site designs alone does not need Azure

                    Most SharePoint site templating implementations which use PnP also use Azure. Certainly if self-service is involved, the typical arrangement is to have users request the site through a form, which adds an item to a list. Because site creation/template application takes some time, it needs to be an async process and so somewhere in there is usually an Azure queue with an Azure web job or Azure Function – this does the heavy lifting, and then e-mails the user and some administrators when the site is available. The PnP provisioning library provides much of these building blocks.

                    However, we regularly run into organizations which are using Office 365 and it’s services, but do not use Azure or any competing cloud platform such as AWS yet. Of course, any Office 365 implementer knows that by using Office 365, the org is actually using Azure AD underneath, but really we’re talking about whether it’s possible to deploy remote SharePoint code such as PnP to the cloud. Often the InfoSec or compliance groups have not yet validated whether this is OK for the org, and there might be valid reasons why Office 365 is OK but other cloud services are not (yet).

                    So, it might be compelling that site designs themselves bring no requirement for Azure. Sure, you’re limited to the templating options provided by site designs, but the “engine” which is applying the template to the site is Microsoft’s code running within the Office 365 service – no custom code is needed whether PnP or not, and therefore the infrastructure requirements are somewhat simpler.

                    6. Site designs cannot be used on-premises, but PnP site templates can..

                    Not too much to say here beyond that. Will site designs come to on-premises SharePoint in the future? Difficult to say, but it’s worth remembering that PnP site provisioning can be used in online and on-prem scenarios.

                    7. Limitations of site designs

                    One big caveat if you’re hoping to use only site designs for your site templates is that you’re currently limited to to what can be accomplished in a site design. The list of things you can add/change in the site is currently:

                    • Add list:
                      • Set title
                      • Set description
                      • Add column
                      • Add content type (note – it must exist already! Site designs cannot provision new content types yet)
                      • Set field custom formatting (with the new JSON-based formatting)
                    • Apply theme
                    • Join a hub site (although hub sites are not yet launched)
                    • Set site logo
                    • Add navigation link
                    • Trigger a Microsoft Flow

                    NOTE – this list will change over time. See the site design JSON schema reference for the latest picture and details of each operation.

                    When I think about the other things we often change (using a PnP template) – changing the site locale/region settings, activating features, provisioning a new home page, adding and configuring web parts, setting the site access requests recipient, changing content types/views/applying versioning settings etc. on libraries – it becomes apparent that things are very limited indeed. For us, this is a complete blocker to the idea of using site designs on their own at the moment. Fortunately, the ability to call a Microsoft Flow is intended for you to supplement what the site design/site script is doing – so let’s explore this idea.

                    The “site designs + PnP” approach

                    In brief, the Flow can trigger some remote code you have to perform other configuration of the newly-created site. This allows you to chain a bunch of other things on to what you were able to do with the site design – for example, actions in my list of things not possible purely in site designs. Of course, the logical thing to do here is actually to apply a PnP template to the site as we would have done before site designs. The pattern is:

                    1. Site gets created from site design
                    2. Site design steps are applied
                    3. Custom Microsoft Flow is called – this puts an item onto an Azure queue with details (e.g. URL) of the new site
                    4. The Azure queue uses a QueueTrigger to start an Azure Function (or web job if you prefer)
                    5. The function applies a PnP template to the site

                    There’s some pretty good early documentation on this approach in Calling the PnP Provisioning Engine from a Site Script. That article shows using a function written in PowerShell which authenticates back to Office 365 using SharePoint Add-in authentication, but you might also choose a C# or node.js code approach which uses Azure AD and ADAL.NET/ADAL.js to authenticate back. Either way, there’s some work to do in Azure to get this running.

                    The benefit of course, is that you unlock the ability to do anything you need to meet the requirements of the site, but can take advantage of the out-of-the-box UI for creating sites (and the fact that things are nicely baked-in to Office 365/SharePoint Online). Given that PnP site provisioning continues to expand it’s capabilities and we can now automatically deploy app packages containing SPFx web parts and extensions, or even SharePoint Add-ins, this approach will be common I feel. Indeed, I think we will implement “minimal” site designs which basically only call a Flow, and the entire template implementation is handled in a PnP template.


                    It might sound like I’m down on site designs somewhat from the points I’m raising, but I’m not. I think this is a great evolution in SharePoint Online – no longer is all of a site templating solution is left to the implementer, since Microsoft are now taking care of some elements (however small to start with). I love the fact that some thought was given to how to go beyond the capabilities of site designs, and I’m sure the engineering teams were thinking specifically about how PnP templates could be incorporated. If I was king for a day, I would have preferred that the existing PnP template schema was used as the foundation for site designs in the first place (instead of introducing another approach to templating with a new JSON schema) – however, I do understand that the PnP engine is open source/community-driven and is not part of the core Office 365 platform, so perhaps that was part of the reason.

                    The introduction of site designs certainly means that there are more options around SharePoint collaboration and site provisioning strategies! Being equipped with as much information as possible is wise – this will help you make the right decisions for you/your organization’s context..

                    Also remember that site designs are still in preview (currently being rolled out to Targeted Release tenants) – hopefully it won’t be too long until the initial release hits General Availability, and the capabilities expand along the journey..

                    Reference -