Page templates are really useful for helping content authors to create news and pages, and bringing unified feeling throughout sites, for example in your intranet. Currently, when page template is created, it is stored to SitePages library of the current site and it will be only available there. In many cases organizations need to have unified templates on all sites in a hub or even all available communication sites.

On this blog post I’m focusing of distributing page templates with PnP PowerShell and PnP provisioning templates. Solution can be easily automated with Azure Functions or Runbooks.
First example is distributing templates from a hub site to all sites linked to it. Second example is distributing templates to all communication sites available in your tenant. Authentication to SharePoint Online is made with Azure AD registered application, which uses a client id and a certificate for authentication. That way I don’t need to take care of user-level permissions on SharePoint sites. On Azure AD, Sites.FullControl.All SharePoint permission is granted to the application.

You can find detailed guide how to setup App authentication with certificate in this PnP PowerShell article: https://github.com/pnp/PnP-PowerShell/tree/master/Samples/SharePoint.ConnectUsingAppPermissions
Distributing templates on a SharePoint hub
If you want to distribute same page templates in a hub, most logical place to maintain those templates is the hub site.
#1) Connect to the hub site with app-only authentication
Connect-PnPOnline -Url $hubSiteUrl -Tenant $tenant -ClientId $clientID -Thumbprint $certificateThumbprint
#2) Get a list of sites connected to a hub
You can get a list of sites connected to a hub with Get-PnPHubSiteChild cmdlet. It returns a list of site urls.
$sites = Get-PnPHubSiteChild -Identity $hubSiteUrl
#3) Get templates from a hub site
Page templates are retrieved with a provisioning template including all client side pages.
$basetemplate = Get-PnPProvisioningTemplate -IncludeAllClientSidePages -Handlers PageContents,Pages -OutputInstance -Schema LATEST -PersistBrandingFiles
New template object is created and all client side pages with PromotedAsTemplate property set to true are added to the new template.
$template = New-PnPProvisioningTemplate
foreach($page in $basetemplate.ClientSidePages)
{
if($page.PromoteAsTemplate -eq $true)
{
$template.ClientSidePages.Add($page)
}
}
#Including images added to a template
$template.Files.AddRange($basetemplate.Files)
#4) Loop through connect sites and apply a template
foreach($site in $sites)
{
$connection = Connect-PnPOnline -Url $site -Tenant $tenant -ClientId $clientID -Thumbprint $certificateThumbprint -ReturnConnection
Apply-PnPProvisioningTemplate -InputInstance $template -Connection $connection
}
Distributing page templates to all communication sites on the tenant
For distributing templates to all communication sites on your tenant, I suggest creating a separate site for hosting page templates. That could be a same site, where organization asset libraries for images and document templates are hosted.
Process is quite similar as in the first example.
#1) Connect to a site hosting templates
Connect-PnPOnline -Url $templateSiteUrl -Tenant $tenant -ClientId $clientID -Thumbprint $certificateThumbprint
#2) Get all communication sites on your tenant
For getting all communication sites, you need to use Get-PnPTenantSite cmdlet with Template attribute. Site template for communication sites is SITEPAGEPUBLISHING#0.
Get-PnPTenantSite -Template SITEPAGEPUBLISHING#0
#3) Create a provisioning template (as in first example )
$basetemplate = Get-PnPProvisioningTemplate -IncludeAllClientSidePages -Handlers PageContents,Pages -OutputInstance -Schema LATEST
$template = New-PnPProvisioningTemplate
foreach($page in $basetemplate.ClientSidePages)
{
if($page.PromoteAsTemplate -eq $true)
{
$template.ClientSidePages.Add($page)
}
}
foreach($site in $sites)
{
$connection = Connect-PnPOnline -Url $site -Tenant $tenant -ClientId $clientID -Thumbprint $certificateThumbprint -ReturnConnection
Apply-PnPProvisioningTemplate -InputInstance $template -Connection $connection
}
Afterword
As you can see, distributing page templates with PnP PowerShell is quite simple and requires just few lines of code. When automating page template distribution, remember to communicate it clearly with content authors and stakeholders. They might discover that it’s very useful to modify distributed templates on a site level, for example adding site specific ready-made content on templates. All of these changes are overwritten with this approach. Also when planning centralized distribution of templates, include all stakeholders to planning to getting most suitable set of templates.
You can find both PowerShell script examples from my GitHub repository:
https://github.com/mpaukkon/SharePoint/blob/master/PowerShell/Copy-SharePointPageTemplateFromHub.ps1
Just came across your Blog by accident.
Great content. Currently, I have a project where I can make use of your code.
Thank you for sharing.
#SharingIsCaring
LikeLiked by 2 people
Hi Matti,
Thanks for this helpful blog post!
Do you see any chance to avoid export all pages from the site collection as first step and just filter to configure the export to the subfolder “templates”?
Thanks,
André
LikeLike
I tried to find filtering options quickly while writing this blog but didn’t find any easy solution for it.
LikeLike