For the last few months, I’ve been working on a few new solutions where clients need to easily create new project sites in SharePoint.  These customers have found that by using Modern Team & Communication sites, Hub sites, Office 365 Groups and Microsoft Planner they can provide a compelling platform for a wide range of project management requirements. 

Each client has unique requirements for the specific components that they need for each project site.  But in each case, there have been common requirements that each of my customers share…

  1. Need to customize a Modern Team site with a unique set of content types, columns, home page layout and other features to support their own project management approach.
  2. Ability for users or IT to easily spin up new project sites, and have each site contain the appropriate configuration (columns, content types, pages, web parts, permissions, etc.)
  3. Enable users across projects to easily access and share common project resources through use of a Hub site.

To implement these solutions, I’ve leveraged a combination of Office & SharePoint technologies including:

  • PnP Powershell
  • Site Designs / Site Scripts
  • Microsoft Flow
  • Azure Storage Queues
  • Azure Functions / Azure Automation

The end result is a solution that behaves like this:


Although this type of solution has a lot of moving parts, the end result is a solution that offers incredible flexibility to support changing client requirements in the future. 

If you’re not already familiar with these components, Microsoft provides great documentation for PnP Powershell and the overall PnP Provisioning Engine, so you may wish to start with these articles first.  Since the major setup steps are well documented elsewhere, this blog series will cover various tips and tricks (and lessons learned) that I encountered while implementing my customers’ provisioning solutions.

Bakground on PnP Powershell

But before we jump into the first “tip”, lets review some basics of PnP Powershell…

With PnP Powershell, the easiest way to generate a PnP provisioning template from a site is with this cmdlet:

Connect-PnPOnline “https://[yourtenant].sharepoint.com/teams/[YourSite]

Get-PnPProvisioningTemplate -out “MyTemplate.xml”

This command will generate a site provisioning template that contains all aspects of your site.  When you generate a provisioning template like this, your MyTemplate.xml will include any customizations that you created in the site (lists, libraries, content types, columns, web parts, navigation, security, etc.) along with definitions for all of the Out of the Box components in a modern team site.

If you execute this Powershell cmdlet on a brand new (uncustomized) modern team site, the resulting Xml file shall contain 890 lines of XML including :

  • 233 lines for OOTB site columns
  • 180 lines for OOTB site content types
  • 306 lines for OOTB libraries

Now let’s say you have a modern SharePoint team site and  you have customized the site by adding some custom site columns, content types, lists and document libraries.  You’ve also added some web parts to the home page and customized the left navigation.

If you generate a provisioning template for your customized site, the Xml file created shall be larger as it will contain the OOTB components and your custom components.  Now that you have a customized “MyTemplate.xml” you could use that template to apply your customizations to a new modern template site using this PnP Powershell cmdlet:

Connect-PnPOnline “https://[yourtenant].sharepoint.com/teams/TestSite001

Apply-PnPProvisioningTemplate –path “MyTemplate.xml”

One of the best parts about PnP Provisioning is that you can re-apply a template to the same site multiple times.  The provisioning engine is very smart about applying changes from the template to the site.  For elements that have not been changed, the provisioning engine simply skips those items.  So even though our template contains definitions for existing libraries like Site Assets, Style Library etc, if we have not customized those things there is no problem to re-apply the template that contains those definitions.

This also means that if you apply a template to a site, then make a small tweak to your template, you can apply the revised template to the existing site and it will simply apply the changes.

Tip # 1 – Customize your PnP site templates

Although the PnP Provisioning engine does an excellent job about ignoring definitions that already exist, you may still wish to customize your templates to make them smaller and more modular.  Personally, I tend to delete the the XML definitions for the out of the box Fields, ContentTypes and Lists from my template XML file, to make the template easier to review in the future.

Removing the OOTB lists is pretty easy, but removing the OOTB Fields and ContentTypes is much more tedious.  If you open your provisioning template XML file in your favorite XML editor, and collapse all sections you can see exactly where the OOTB ListInstances are stored.  In the example below, my template has one custom list (a library named “Sales”) and four OOTB libraries: Documents, Form Templates, Site Pages and Style Library. 

Assuming we have not customized the OOTB libraries, then we don’t need to keep them in the template, as we’ll have a copy of these libraries created by SharePoint in each new team site.  Therefore, I’ll delete the pnp:ListInstance elements for the OOTB libraries:

Before Delete

This Provisioning template XML only contains definitions for the site’s lists and it is 326 lines.

After Delete

Note that the provisioning template XML is now down to 59 lines


It’s been my experience that there are numerous scenarios where you’ll need or want to manually edit the provisioning template XML file.  By starting with a vastly smaller Xml file, our future tweaking to the template file will be easier.

Tip # 2 – Modularize your PnP site templates

In addition to removing redundant or unneeded components from the template, you may also find value in refactoring templates to make them more re-usable.

Consider a scenario where you’re defining a site template to manage projects.  Your company has various divisions that all manage projects, so we want a site template that is customized to our company’s project management standards.  Each project site needs a consistent set of custom columns, content types, libraries, lists, web parts, etc.  However, within each department, they may wish to customize the homepage and left navigation for their project sites differently from the standard company project sites.

It is easier to manage this type of requirement by creating PnP site templates that are modular and re-usable.  In this case, we may want to generate two provisioning templates for each project site:

  • A template for the “information architecture” (e.g. ProjectIA-Template.xml)
    • Contains definitions for site fields, content types, lists and libraries
    • One version of this template shall be used across all departments
  • A template for the layout and web parts on the home page along with left navigation (e.g. ProjectUI-DeptX-Template.xml)
    • Contains definitions for home page and left navigation
    • A unique version of this template may be created for each department

To generate modular templates, we use the Handlers parameter within the Get-PnPProvisioningTemplate cmdlet.  For example:

  • Get-PnPProvisioningTemplate -out “ProjectIA-Template.xml” –Handlers “Fields,ContentTypes,Lists”
  • Get-PnPProvisioningTemplate -out “ProjectUI-DeptX-Template.xml” –Handlers “Pages,PageContents,Navigation”

A few common examples of PnP Provisioning Handlers include:

Handler Name Description Represented in template XML as


Site columns



Site’s ContentTypes



Site’s lists and libraries



Members of SharePoint groups in the site



Layout and webparts on the home page




Left and Top navigation links


Note: For a full list of all PnP Provisioning Handler values, check out OfficeDevPnP.Core in Github


That concludes the Part 1 of this series on PnP Provisioning tips and tricks.  I’ll follow up this article soon with Part 2.


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 )

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s