M365 Show -  Microsoft 365 Digital Workplace Daily
M365 Show with Mirko Peters - Microsoft 365 Digital Workplace Daily
Automating SharePoint Online with Site Scripts and PnP Provisioning
0:00
-18:34

Automating SharePoint Online with Site Scripts and PnP Provisioning

Ever spent an entire afternoon manually tweaking a new SharePoint site—only for the next one to look completely different? There’s a smarter way to guarantee every site matches your vision, without losing hours to repetitive setup.

Today, I’ll show you the exact steps to automate branding, lists, and permissions using Site Scripts and PnP. Why keep repeating yourself when you can build it once and scale instantly? Stick around to see how you can finally make SharePoint play by your rules.

Why Manual SharePoint Sites Always Drift—and How Site Scripts Get You Back on Track

If you’ve ever sat down to create a SharePoint site with high hopes, only to revisit it a few days later and wonder what happened, you’re not alone. You map out the perfect site layout—maybe sketch some ideas for a consistent logo, pick just the right shade of blue for the header, list out all the custom permissions your department needs. But then it’s time to build another site. Suddenly, you’re flipping through your notes, pasting snippets from a Word doc last updated before Teams even existed. What started as an organized process starts to feel more like remembering all the right spices when you’ve left the recipe at home. Things drift. Someone sets the wrong banner color just once, and now it’s quietly become the default. Or maybe someone forgot to recreate a specific list, and now there’s confusion about where files are supposed to go.

It’s the sort of chaos that sneaks up slowly. Even when you try to stay consistent with templates or checklists, little inconsistencies creep in. You’ll notice the first site is using the corporate font, but the next one mysteriously reverts to Arial. One site has a document library laid out with sorted columns, but somewhere along the line, the sorting gets lost. And permissions—a favorite source of headaches—always seem to get muddled. Maybe in a rush, someone forgets to break inheritance on a confidential folder, and now everyone in the company stumbles into files meant for the Finance team only. Templates help, but they’re only as reliable as the person executing each step. The more sites you spin up, the harder it is to guarantee they look and work the same way every time.

Let’s give this a real-world spin. Imagine you’re launching a new department site on Monday. You’re careful with the branding, spend extra time adding a custom list for asset tracking, and you even double check the permissions. Fast forward to Friday—a new site is live for another team. You pop in to review it, and instantly see problems. Fonts are off. The logo is the wrong size. The custom asset list is missing. Permissions are inherited straight from the parent, opening up sensitive data to everyone. Two sites, less than a week apart, but you’d never guess they came from the same setup process. It’s not a lack of effort; it’s just inevitable drift. The more manual effort and memory involved, the less likely two sites ever wind up matching.

So, Site Scripts show up promising to fix this. But there’s this nagging question: is a long string of JSON commands actually going to make things easier, or is it just another layer you’ll end up managing? Here’s what Site Scripts actually bring to the table—the magic is in the instructions. You write out, in plain text (JSON), exactly what you want SharePoint to do. “Apply this color theme. Upload this logo. Create this list.” Each step, spelled out in a way SharePoint understands, so you’re not relying on memory or someone’s best guess. It’s like finally getting your hands on a recipe card that actually lists the right measurements.

Branding gets locked in by default. You upload a logo once; every new site is stamped with it. Headers and navigation keep the same look—whether you’re spinning up a single-team site or launching ten department hubs. The days of “wait, did I forget to update the header again?” are over. And it doesn’t just stop at coloring. You can bake in structure, specify which lists to build, and customize the user experience at the moment the site is created.

Seeing is believing. Picture the difference: one site manually built, with tweaks from memory; the other using a Site Script, where every color, logo, and list appears exactly as planned, every single time. It’s not a subtle improvement. Even a quick glance shows you which approach is running on autopilot, and which one is clinging to manual fixes. And here’s the surprise—there’s no programming degree required. Site Scripts are for admins who’d rather be efficient than deeply technical, letting you enforce standards without learning to code.

But, of course, branding is just the front door. What about everything inside—lists, libraries, the actual content that makes a SharePoint site useful? That next step takes you from pretty sites to ones that really get work done, and that’s where the real taste of automation begins.

Building Your First JSON Site Script: Branding, Lists, and a Taste of Automation

So now you’ve seen what Site Scripts promise, but let’s talk about what actually happens when you try to build one yourself. Imagine sitting down at your workstation with a blank JSON file open in Notepad. No templates. Just an empty screen, blinking at you, daring you to make the first move. Most of us start by staring at the documentation, maybe even copy-pasting, only to realize this thing has its own logic. Miss one bracket or put a comma in the wrong spot and you’re rewarded with an error that reads like someone mashed the keyboard. For most admins, the experience feels uncannily like trying to follow a recipe written in shorthand: it’s technically there, but the smallest misstep throws the whole thing off.

Let’s break through the fog with a real example—a minimal Site Script that applies a company theme and adds a simple list. Even in its simplest form, what’s in this file governs how your SharePoint site looks and functions the moment it’s created. You’ll see keys like “verb,” which tells SharePoint what action to perform, “applyTheme” for branding, and “createSPList” for new lists. If you’re thinking this all feels a bit like building IKEA furniture—for SharePoint—then you’re not far off. Everything has to happen in a certain order, and the labels might be confusing at first, but the end result is solid if you follow the instructions step by step.

Pretend for a minute you want all your project sites to launch with company colors—no random purples or retro gradients—and a tracker list for action items. Your JSON might start with an “actions” collection, basically the heart of your script. The first action:

{
"verb": "applyTheme",
"themeName": "Contoso Blue"
}

This line means SharePoint will snapshot your default look and apply it to every site using this script. No more nightmares where one department has a teal banner while everyone else is navy. Then comes the structure part:

{
"verb": "createSPList",
"listName": "Action Tracker",
"templateType": 100,
"subactions": [
{
"verb": "setTitle",
"title": "Action Items"
}
]
}

Here, it calls for a fresh SharePoint list named “Action Tracker,” built on the generic custom list type. Under “subactions,” you can fine-tune details—maybe set the default view or add columns—but let’s keep it simple for now. Think of it like making lasagna: if you skip the noodles, it falls apart. If you add the wrong list template, you won’t get what you’re expecting. Each action, down to the order, needs to be right for things to come out as planned.

Once your script is saved, SharePoint doesn’t magically know it exists. You need to register your Site Script and then associate it with a Site Design—a reusable package that users can pick when creating a new site. Inside the SharePoint admin center, you go to the Site Scripts section, upload your JSON, and give it a name you won’t forget later. Then, create a Site Design and point it to your script. When users choose this design, SharePoint runs your instructions the moment a new site spins up. You don’t have to hover over them or check settings the next day.

Watching this in action feels, frankly, pretty refreshing after years of manual site tinkering. The site pops up with the company’s branding perfectly in place, your “Action Tracker” list right there on the homepage, and not a single errant color or missing list. If another department needs the same template tomorrow, you can give them a site that matches—without ever redoing the work or trusting that someone remembers how you “did it last time.” That’s the biggest win here: the reduction in friction and the confidence that every site starts on the right foot.

For most admins, this covers almost everything they ever wish would “just work” during site creation. No more missed lists, off-brand banners, or forgotten manual steps. Even this basic setup solves the majority of headaches you’ll find in day-to-day SharePoint management. But as much as this automates, there are still gaps. Not everything can be set in stone with JSON. So, what if you want to automate deeper—like tweaking permissions or dropping in custom web parts, or handling those settings that just don’t appear in the JSON reference? That’s where things start to get interesting.

Where Site Scripts Stop—and PnP PowerShell Picks Up the Slack

If you’ve ever tried to push SharePoint automation beyond just branding and simple lists, then you’ve probably run into the infamous Site Script limitations. You get your JSON script working like clockwork—color palette locked down, that must-have Action Tracker list in place—but you quickly notice the fine print in the documentation. Need to grant unique permissions to a document library? Want to roll out a custom web part tied to your departmental workflow? Site Scripts just give you a polite shrug. There it is in the support matrix: “not supported.” Suddenly, the automation that promised freedom now has you scrambling for manual fixes again.

And let’s be honest, the whole point of automation is to avoid those manual steps. You start out with the best intentions. But the minute you have to circle back and break list inheritance by hand or fiddle with security groups, the value slips away. Before long, you’re back to updating checklists, keeping tabs on who got the “special” setup, and making side agreements with department owners to handle sensitive data access manually. The more custom your requirements, the more you’re stuck straddling two worlds—the partially automated and the semi-broken.

This is when PnP PowerShell quietly becomes a lifesaver. If JSON outlines what a site should look like, PnP PowerShell digs underneath and handles the things Site Scripts can’t reach. The real trick is that you’re not ripping out your Site Scripts; you’re extending their power. Think of Site Scripts as the blueprint and PnP PowerShell as the toolkit for the things that need an extra touch. They actually fit together surprisingly well, even if Microsoft’s documentation makes it seem like they belong in different universes.

Take permissions, for example. There’s no reliable way in Site Scripts to say, ‘Only marketing gets access to this list—everyone else, keep out.’ If you’re managing sites for HR, Finance, or Legal, that’s not a minor gap. With PnP PowerShell, you can set up a script—often just a couple of lines—that targets your freshly generated site and does things JSON can’t. You might run a command to remove default permissions, create new SharePoint groups, and assign list-level access all in one go. No UI clicking, no second-guessing if someone remembered every step.

Picture this: your HR team needs a new communication site. Site Script handles the basics—branding, homepage structure, maybe a couple of lists for onboarding and documents. But HR data needs to be locked down, so you run your PnP PowerShell script right after the site spins up. The script finds the “Employee Records” list, breaks permission inheritance in a single command, and grants access only to the HR group. The next time you revisit the site, you’re not stuck playing detective, tracking down why former interns can browse private files. It just works.

The value in this approach is that you’re not forced to pick a single path. Use Site Scripts for their structure and predictability. When you run into a wall—the built-in “not supported”—that’s your cue to let PnP PowerShell unlock the next level. Together, they cover nearly every aspect of SharePoint provisioning you’d actually want in the real world. You’re not patching around their limits; you’re using each for what it’s good at.

This handoff between tools is smoother than you’d think. An admin can trigger a Site Script from the SharePoint UI, then automatically launch a PnP PowerShell process in the background—maybe tied to a Flow or a scheduled task. You end up with the full build-out: branding in place, structure set up, and those pesky permissions no longer an afterthought. No manual override, no chasing down missed configurations.

And here’s where it really pays off—power users or IT admins don’t have to make trade-offs about what’s possible. Instead of dealing with another compromise or skipping “just one” security step because it’s inconvenient, you’re setting up automation that closes all those loopholes for you. The combination is what makes an enterprise roll-out scalable. It also means you’re not up at 2 a.m. fixing access mistakes because someone relied on memory instead of a script.

But as these workflows start to multiply, the story changes. The cracks start to show when you’re rolling out at scale—not just a handful of sites, but dozens or hundreds. Suddenly, perfect automation becomes more fragile. Now, every update, requirement tweak, or Microsoft change can ripple through your system and break things you thought were locked down.

Avoiding Pitfalls: Best Practices for Reliable, Repeatable SharePoint Automation

It’s tempting to feel unstoppable once you’ve finally got Site Scripts and PnP PowerShell humming together. You might watch one new SharePoint site spin up after another, everything looking on-brand, with the right permissions sliding into place. But the reality sets in around your tenth or twentieth rollout. It doesn’t always break in ways you notice at first. Sometimes, you get that request for a “minor” tweak—maybe a new column on a list or a new department needs a slightly different permission model. Or Microsoft slips in an update on a Thursday night, and suddenly your tried-and-true script decides this is the perfect time to fail. When you’re the admin fielding those calls, nothing feels more like déjà vu than realizing every new site this week is missing a critical list, or permissions defaulted wide open. Not a great start to anyone’s Friday.

Let’s get specific about what actually goes wrong at scale. The first and most common trap is version drift. It’s when your Site Scripts, PowerShell scripts, and actual sites slowly move out of sync over time. Maybe you update your template for one project, but someone else spins up a site with the previous version two days later. You end up with sites launched this month that don’t match each other—same design, totally different guts. The drift gets worse if there’s no single source of truth, and it’s shockingly easy for teams to be running a Frankenstein’s monster of versions without realizing it. Then you have over-customization—a quick tweak here and there for “just this one department” multiplies. The next thing you know, you’re supporting three flavors of site scripts, with one-off PowerShell scripts you can barely trace back to the original. When something breaks, you have to choose whether to fix it everywhere or let the odd ducks live on as exceptions. Neither feels great.

Another pitfall shows up when scripts don’t fail gracefully. Site Scripts and PowerShell can both stop mid-run if something isn’t exactly right. Maybe someone renamed a theme in SharePoint, or a required column disappears from your JSON. If your automation isn’t set to log failures or continue past non-critical errors, the whole setup stalls. The worst part? You might not hear about it until weeks later, when a user points out their site launched half-baked. If you’re missing error handling, you often find out after a dozen sites have already rolled out incomplete. That’s the moment the helpdesk lights up and suddenly, your “savings” from automation evaporate into high-priority tickets.

Now, these headaches aren’t inevitable, but you have to plan for them. Start with source control. It sounds simple, but far too many admins keep scripts in a shared drive or in someone’s downloads folder. Use a system like GitHub, Azure DevOps, or even SharePoint itself to manage changes. That way, every tweak creates a breadcrumb trail you can audit or roll back. It also helps keep your scripts from wandering off in different directions. Next, comment your scripts—both in JSON and PowerShell. Those little side notes in your code make it much easier six months from now to remember why you set that one list template or when you added a new field. A few lines of plain English can save hours of guesswork or rewrites down the road.

Testing in a sandbox environment is next-level insurance. It’s tempting to skip this step—especially if you’re confident in your script. But production SharePoint sites are not where you want to learn you’ve swapped two actions or left a permission wide open. Build out a simple dev tenant or a team sandbox. Run every update there first, and only roll out to production once you know it’ll work. It’s an extra half hour per change, but it’s nothing compared to the time spent cleaning up after a missed detail.

Let me give you a real example from the real world: a nonprofit adopted automated provisioning to save the team time on each onboarding site. They built a solid workflow—Site Scripts for layout and lists, PnP for permissions and content deployment. It worked perfectly—at first. Then leadership decided every site needed to capture new data due to a compliance review. The original workflow wasn’t tracked in source control, and the lead admin who wrote it had already moved on to another team. No comments, no documentation. They spent three days reverse-engineering their own automation just to add one column. The hours they saved in year one all got erased in just one round of updates.

Monitoring and error logging are not glamorous, but they’re the invisible safety net that separates robust automation from accidental chaos. Set up logs for every script run. If something fails, get notified before users do. Even a simple email alert stacked with error output can keep you ahead of the curve. This approach gives you space to fix problems before they impact your community of users, instead of getting calls about why a site went sideways. With the right habits—source control, comments, sandbox testing, and decent logging—you can build reliable automation that evolves as requirements change.

The big lesson is simple. Automation is a living thing. Scripts should be tracked, reviewed, and updated over time, not filed away and forgotten. Treat your workflow as a portfolio, not a final project. That way, you can actually trust your process to keep up with whatever SharePoint or your business throws at it.

Once that’s in place, you’re no longer just keeping up—you’re steering the direction of your SharePoint environment, and that opens up new opportunities for your team to focus on what really matters.

Conclusion

If you’ve ever felt stuck manually rebuilding the same SharePoint site, Site Scripts and PnP PowerShell give you a better approach. Instead of repeating steps and hoping details stick, you can now roll out sites that look the way you want every single time. That frees up your team to work on projects with actual value, not just maintenance. For admins who want shareable, repeatable results, building out your toolset now pays off for months. Subscribe if you want more strategies for everyday Microsoft 365 headaches, and let us know in the comments what your biggest automation challenge looks like.

Discussion about this episode

User's avatar