Anything you do twice in the SharePoint admin UI, you should script. PowerShell is the difference between a consultant who spends an afternoon clicking through site settings and one who runs a tested script across fifty sites in two minutes. This article maps out the SharePoint PowerShell landscape and shows the patterns I reach for on almost every engagement.

Know your modules

There isn't one "SharePoint PowerShell" — there are several, and choosing the right one matters:

The SPO Management Shell is for tenant-level tasks; PnP PowerShell is for everything inside a site. On most projects you use both — SPO to create the site, PnP to fill it.

Connecting

# Tenant administration
Connect-SPOService -Url "https://contoso-admin.sharepoint.com"

# Site-level work with PnP
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/ops" -Interactive

Prefer interactive or certificate-based auth over storing credentials in scripts.

Provisioning a list with fields

The bread-and-butter task: stand up a list with a defined schema, repeatably and idempotently. PnP makes it terse:

# Create the list only if it doesn't already exist
$list = Get-PnPList -Identity "Contracts" -ErrorAction SilentlyContinue
if (-not $list) {
    $list = New-PnPList -Title "Contracts" -Template GenericList -OnQuickLaunch
}

# Add fields (Add-PnPField is safe to re-run with -ErrorAction)
Add-PnPField -List "Contracts" -DisplayName "Contract Value" `
    -InternalName "ContractValue" -Type Currency -AddToDefaultView

Add-PnPField -List "Contracts" -DisplayName "Status" `
    -InternalName "ContractStatus" -Type Choice `
    -Choices "Draft","In Review","Approved","Archived" -AddToDefaultView

# Index a column you'll filter on (matters for large lists)
Set-PnPField -List "Contracts" -Identity "ContractStatus" `
    -Values @{ Indexed = $true }
Write provisioning scripts to be idempotent — safe to run repeatedly. Check for existence before creating, and your script doubles as both an installer and a repair tool.

Bulk operations

Need to update hundreds of items? Pull them once, loop, and let PnP batch the writes:

$items = Get-PnPListItem -List "Contracts" -PageSize 500

foreach ($item in $items) {
    if ($item["ContractStatus"] -eq "Approved" -and
        $null -eq $item["ReviewedDate"]) {
        Set-PnPListItem -List "Contracts" -Identity $item.Id `
            -Values @{ "ReviewedDate" = (Get-Date) } | Out-Null
    }
}

Content types the scripted way

Content types are tedious to build by hand and error-prone to keep consistent across sites. Script them:

$ct = New-PnPContentType -Name "Vendor Contract" `
    -Group "Contoso Content Types" -ParentContentType (Get-PnPContentType -Identity "Document")

Add-PnPFieldToContentType -Field "ContractValue" -ContentType "Vendor Contract"
Add-PnPFieldToContentType -Field "ContractStatus" -ContentType "Vendor Contract"

# Attach it to a library
Add-PnPContentTypeToList -List "Contract Documents" -ContentType "Vendor Contract" -DefaultContentType

Automating the full site lifecycle

Tie it together: create the site collection with the SPO shell, then hand off to PnP to configure it:

# 1. Create the site (tenant admin context)
New-SPOSite -Url "https://contoso.sharepoint.com/sites/project-atlas" `
    -Owner "admin@contoso.com" -StorageQuota 1024 `
    -Title "Project Atlas" -Template "STS#3"

# 2. Configure it (site context)
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/project-atlas" -Interactive
# ... New-PnPList / Add-PnPField / Set-PnPWebTheme etc.
Site creation in SharePoint Online is asynchronous. After New-SPOSite, poll with Get-SPOSite until status is Active before you try to connect and configure it, or your PnP commands may fail with a 404.

From scripts to templates

Once your provisioning logic grows past a few dozen lines, graduate from imperative scripts to the PnP provisioning engine: capture an entire configured site as an XML template with Get-PnPProvisioningTemplate, then re-apply it anywhere with Apply-PnPProvisioningTemplate. I cover that approach in depth in a later article — but the imperative cmdlets here remain the right tool for surgical, one-off changes and for the glue around the declarative templates.

Practical habits

PowerShell is the consultant's force multiplier. The investment you make turning a manual checklist into a tested script pays back on the very next environment you have to stand up.

DS

Dhaval Shah

Cloud Solution Architect — 18+ years across SharePoint, Microsoft 365, and Azure AI.