Modern web parts provisioning in SharePoint Online

Office 365 and SharePoint Online in particular rush in the direction of Modern UI and UX. The modern sites with modern pages have a number of advantages starting with simplicity for end users who manages the content and finishing with OOTB responsiveness and mobile friendliness. There is a bunch of great web parts to use out of the shelf as well as a rich tooling and the framework for rapid development of custom ones. After a while, a question of modern sites managing and automated provisioning appears. In this post, I'm going to reveal and investigate some options for pages and web parts provisioning.

Modern page structure quick overview

The modern page is a page in SitePages on a modern SharePoint site which provides a capability of organizing content within the page. A page can be configured with sections (rows), a section can be dynamically divided into columns or declared as a full-width section, then web parts can be added into a column. All of these gives a flexible way of managing the visual representation of information on the page.

Modern web part quick overview

Only modern web parts can be located on a modern page. Modern web parts can be separated to OOTB provided by Microsoft and custom 3rd party developed using SharePoint Framework (SPFx). OOTB web parts can't be changed, but all the web parts could be configured with properties defined during development time. Sometimes changing properties, one can receive absolutely different experience within the same web part.

Modern web parts are rendered on the pages as canvas controls, so "canvas control" is the second name for modern web parts.

Each web part has its own unique id, alias, version, manifest and data. The simplest way to research web parts' metadata is to add web parts you're interested in on the page, provide settings in the UI, publish the page and then add ?maintenancemode=true parameter to the URL. This switches page into maintenance mode showing web parts' service information.

Provisioning options

Any developer in the wild should be equipped with provisioning toolchains. Only microscopic solutions should assume manual actions as a rule. I say this words as a mantra to the team members and customers. Depending on preferences and scenarios different approaches can be used for provisioning, but the process should be automated, point or even exclamation mark.

PnP provisioning

PnP provisioning is a set of tools for .Net and PowerShell, which provides cutting edge feature capabilities when it comes to SharePoint Online.

PnP provisioning assumes two approaches: functional code-base provisioning and declarative schema-based processing. So, for example, one can provisiong an artifact using a specific PowerShell commandlet or .Net method or create an XML template based of a schema and apply this template to site.

<?xml version="1.0"?>
<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2018/05/ProvisioningSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.dev.office.com/PnP/2018/05/ProvisioningSchema https://raw.githubusercontent.com/OfficeDev/PnP-Provisioning-Schema/master/OfficeDevPnP.ProvisioningSchema/ProvisioningSchema-2018-05.xsd">
  <pnp:Preferences Generator="OfficeDevPnP.Core, Version=2.26.1805.0, Culture=neutral, PublicKeyToken=5e633289e95c321a" />
  <pnp:Templates ID="PORTAL-PAGES-TEMPLATE">
    <pnp:ProvisioningTemplate ID="PAGES-TEMPLATE" Version="1.0">
      <pnp:ClientSidePages>
        <pnp:ClientSidePage PageName="SamplePage01.aspx" Title="Sample Page 01" Layout="Article" PromoteAsNewsArticle="false" Overwrite="true" EnableComments="true" Publish="true">
          <pnp:Sections>
            <pnp:Section>
              <pnp:Controls>
                <pnp:CanvasControl WebPartType="Custom" ControlId="34f46dbd-abbb-4ff9-be98-7483df537309" Order="1" Column="1">
                  <pnp:CanvasControlProperties>
                    <pnp:CanvasControlProperty Key="PropName" Value="PropValue" />
                  </pnp:CanvasControlProperties>
                </pnp:CanvasControl>
              </pnp:Controls>
            </pnp:Section>
          </pnp:Sections>
        </pnp:ClientSidePage>
      </pnp:ClientSidePages>
    </pnp:ProvisioningTemplate>
  </pnp:Templates>
</pnp:Provisioning>

This XML sample shows configuration of creation SamplePage01.aspx page with one sections and a custom web part placed to the first and the only column in this case.

Having such a template it can be applyed to a site with a bit of PowerShell:

$Connection = Connect-PnPOnline -Url $SiteUrl -UseWebLogin -ReturnConnection;
Apply-PnPProvisioningTemplate -Path $SchemaPath -Connection $Connection;

Where:

  • $SiteUrl is a URL of SharePoint modern site,
  • $SchemaPath is path to the XML template.

Declarative style gives an idea how to organize pages, sections and web parts. Let's investigate canvas control in particular.

<!-- Out of the box web part -->
<pnp:CanvasControl
  WebPartType="Spacer"
  JsonControlData="{&quot;autoHide&quot;:true,&quot;height&quot;:56}"
  Order="1" Column="1"
/>

<!-- Custom web part -->
<pnp:CanvasControl
  WebPartType="Custom"
  ControlId="4f87b698-f910-451f-b4ea-7848a472af0f"
  JsonControlData="{&quot;description&quot;:&quot;Seattle&quot;,&quot;timeZoneOffset&quot;:10}"
  Order="1" Column="2"
/>

The example above shows OOTB web part provisioning definition. For OOTB controls PnP schema has WebPartTypes dictionary, no need in providing ControlIds. For a custom types, ControlId is required. It can be easily found in maintanence mode or web part manifest.

The most annoying part is providing properties, i.e., JsonControlData stored escaped version of properties JSON. Yet you can get used dealing with this rather soon, especially, for some simple cases the props can be provided in XML way:

<pnp:CanvasControlProperties>
  <pnp:CanvasControlProperty Key="PropName" Value="PropValue" />
</pnp:CanvasControlProperties>

A good example of web parts provisioning and modern SharePoint solution in general with all moving parts can be found in SharePoint Starter Kit repository.

PnPjs provisioning

PnPjs, client side libraries for Microsoft 365, wrapper for SharePoint REST API and much more, also provides its mechanisms for dealing with client side pages via REST API.

With REST API, most of the actions with client site pages and modern web parts are in out disposal.

import { sp, ClientSidePage, ClientSideWebpart, ClientSideText } from '@pnp/sp';

(async () => {

  const page = await sp.web.addClientSidePage('SamplePage01.aspx', 'Sample Page 01');

  // Getting existing page
  // const pageFile = sp.web.getFileByServerRelativeUrl(`${webUri}/SitePages/SamplePage01.aspx`);
  // const page = await ClientSidePage.fromFile(pageFile);

  page.sections = [];
  const section = page.addSection();

  // Placing all the webparts in one section

  // Standard text control
  section.addControl(new ClientSideText('HTML content goes here'));

  // Custom 3rd party webpart
  section.addControl(
    new ClientSideWebpart('Custom web part', null, {
      parameter01: 'value 01'
    }, '34f46dbd-abbb-4ff9-be98-7483df537309')
  );

  // Image gallery webpart
  section.addControl(
    new ClientSideWebpart('ImageGallery', null, {
      layout: 2,
      gridSettings: {
        imageSize: 2,
        imageCropping: 1,
        imageAspectRatio: 1,
        lightbox: false
      },
      images: [
        { url: '/sites/hub/SiteAssets/ImageGallery/88876.jpg' },
        { url: '/sites/hub/SiteAssets/ImageGallery/77559.jpg' },
        { url: '/sites/hub/SiteAssets/ImageGallery/77371.jpg' },
        { url: '/sites/hub/SiteAssets/ImageGallery/36732.jpg' },
        { url: '/sites/hub/SiteAssets/ImageGallery/97899.jpg' }
      ]
    }, 'af8be689-990e-492a-81f7-ba3e4cd3ed9c')
  );

  await page.save();

})()
  .then(_ => console.log('Done'))
  .catch(console.log);

Such scripts can be a part of admin applications within SPFx solution for example, can be executed right in the browser using SP Editor extension, or can run in Node.js process.

Wrapping up

Both PnP Provisioning (.Net, PowerShell) and PnPjs scripts are friendly for automated processes and CI/CD. In my opinion these tools are mandatory and de-facto for modern SharePoint developers and administrators.

The second wrapping idea is that it has been never so easy to provision pages and web parts as it is now with Modern cutting edge SharePoint.