SharePoint Framework End User Managed Placeholder Content Part 1

Have you seen the new SharePoint Framework Developer Extensions preview? If not, check it out here! One of the many exciting features included is the ability to inject content into placeholders on all pages. This is a great way to be able to customize the look and feel of your site, but without having the overhead of a custom masterpage, which isn’t available in Modern sites.

In this 3-part series, we’re going to build a solution that will allow end users to easily take our finished package, deploy it on a given site, and manage the content that appears within the placeholders. At the time of this writing, there are only 2 placeholders available (header and footer), but as more placeholders become available (this has already been confirmed by Microsoft) you’ll be able to utilize this same solution to place content in them, without having to update the code, or even deploy the package!

Here’s how we’ll break down the series:

  1. Part 1 – Create the Content Repository for managing your Placeholder content
  2. Part 2 – Inject your managed Placeholder content into your pages
  3. Part 3 – Cache placeholder content in localStorage
  4. Part 4 (New!) – Update code for the 1.2.0 SharePoint Framework Extensions Release Candidate

Without further ado, let’s get started with Part 1!

Part 1 – SharePoint Framework End User Managed Placeholder Content

In order to allow our end users to manage content that will be displayed within the placeholders, we need to provide them with a repository to store this content. We’ll do this by taking advantage of the feature framework and provisioning a list where this data can be managed.

Here are the steps to get up and running:

  1. Launch your favorite command line and make a new directory for the solution:
    md PlaceholdersExtension
  2. Switch to your new solution folder:
    cd PlaceholdersExtension
  3. Run the Yeoman SharePoint generator (haven’t setup your SharePoint development environment before? See this article to get yourself ready, and then come back to this step):
    yo @microsoft/sharepoint
  4. Hit ‘enter’ to accept the default solution name
  5. Select ‘Extension (Preview)’ on the type of client-side component to create
  6. Select ‘Application Customizer (Preview)’ on the type of client-side extension to create
  7. Type ‘PlaceholdersExtension’ as the name of your application customizer
  8. Type a description for the extension if you’d like, or just hit ‘enter’

At this point your solution is being created, and NPM will begin installing several things, so this step can take 1-2 minutes. For reference, your command window should have looked something like the below, prior to hitting ‘enter’:
Command window

Provision the Content Field and List within your solution

Now that you have your solution initiated, it’s time to create the field and list that will allow users to manage the placeholder content.

  1. Assuming you’re utilizing Visual Studio Code, launch your solution via:
    code .
  2. Create a new folder in the root of your solution called ‘sharepoint’ (you can right-click in the gray area below your files in the explorer pane to get the menu to add a new folder)
  3. Right-click your new sharepoint folder and create a new folder called ‘assets’
  4. Right-click your new assets folder and create a new file called elements.xml, utilizing the below for its content:
    <?xml version="1.0" encoding="utf-8"?>
    <Elements xmlns="">
        <Field ID="{32decb18-2917-4565-8458-58e917e2ba8a}"
        <ContentType ID="0x01004d231c0a7ac2475ebce218d74ad6d47b"
            Name="SPFx Placeholder"
            Group="SPFx Content Types"
            Description="Manage placeholders extension content">
                <FieldRef ID="{32decb18-2917-4565-8458-58e917e2ba8a}" />
            Title="SPFx Placeholders"
            Description="SPFx Placeholders"

    What we’ve essentially done is created a new field to store the html end users will edit for a placeholder entry (each placeholder is going to have an entry in our list, which is why the solution will work for new placeholders in the future), added our new field to a new content type, and then we’ve created an instance of a list where we’ll use a custom schema to bind our content type to the list in the next step.

  5. Right-click your assets folder and create a new file called schema.xml, utilizing the below for its content (this schema will add our new column to the default view of the list):
    <?xml version="1.0" encoding="utf-8"?>
    <List xmlns:ows="Microsoft SharePoint" Title="Basic List" EnableContentTypes="TRUE" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/Basic List" BaseType="0" xmlns="">
          <ContentTypeRef ID="0x01004d231c0a7ac2475ebce218d74ad6d47b" />
          <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
            <XslLink Default="TRUE">main.xsl</XslLink>
            <RowLimit Paged="TRUE">30</RowLimit>
            <Toolbar Type="Standard" />
              <FieldRef Name="LinkTitle"></FieldRef>
              <FieldRef Name="SPFxContent"></FieldRef>
                <FieldRef Name="ID" />
          <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
          <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
          <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
  6. Open up config/package-solution.json, and add a comma after the “version” value underneath solution, and add the below text:
    "features": [{
          "title": "Placeholders Extension",
          "description": "Placeholders Extension",
          "id": "7d3631fb-aeb8-4fe4-9d5e-eede52446c9d",
          "version": "",
          "assets": {        
            "elementManifests": [

    Your package-solution.json file should now look like the below, with the exception of a different solution id (and solution name, if you’ve chosen to update that)package-solution.json

  7. We have one more step to take, due to a bug in the extension preview. Navigate to your src/extensions/{SolutionName}.manifest.json file and replace the “$schema” line with the following:
    "$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/client-side-extension-manifest.schema.json",

    (If you’re interested in learning more about why this needs done, read this article)

Deploy Your Solution

We’re now ready to deploy our solution to SharePoint Online. To do this, you must be utilizing a Developer tenant, as extensions are currently in preview mode only.
To deploy your solution, follow the below steps:

  1. Open your favorite command window and ensure you’re in the root folder of your solution
  2. Bundle your solution (this creates the individual manifest, js, and map files) via:
    gulp bundle
  3. Package your solution via:
    gulp package-solution
  4. Note the sppkg file located within your sharepoint/solution folder (You’ll need this in a second)
  5. Navigate to your app catalog site within O365
  6. Select ‘Apps for SharePoint’ from the left-hand navigation
  7. Upload your sppkg file
  8. When prompted if you trust the solution, click ‘Deploy’
  9. Create a new Modern Team Site by selecting the SharePoint app from the app launcher, and click ‘Create site’ at the top of the page (if you can’t find the SharePoint app, you can manually visit this page by appending ‘/_layouts/15/sharepoint.aspx’ to your main tenant url)
  10. Navigate to your new site and select cog -> Add an App
  11. Click the name of your app below in the ‘Apps you can add’ section (if you didn’t update it, it should be called placeholders-extension-client-side-solution)
  12. Select cog -> Site contents (if not redirected) and refresh the page periodically until the app is no longer grayed out, and shows as installed
  13. Note the new ‘SPFx Placeholders’ list, where we can now manage our content by creating new entries with the appropriate placeholder name for title (we’ll populate these records during Part 2 as well)

If you were able to follow along, and everything is working, pat yourself on the back, and take a break. We’ll see you in a bit for Part 2!


Matt Jimison

Microsoft 365 Geek - Husband, father, lover of basketball, football, smoking / grilling, music, movies, video games, and craft beer!

Leave a Reply

Your email address will not be published. Required fields are marked *