Introduction
Modern intranets aren't single sitesβthey're ecosystems of interconnected content spanning departments, teams, and projects. SharePoint Hub Sites provide the architecture to connect these disparate sites into a cohesive experience with shared navigation, unified branding, aggregated news, and cross-site search.
In this comprehensive guide, you'll master SharePoint Hub Sites from architectural planning to enterprise implementation. You'll learn hub site design patterns, association strategies, governance models, and automation techniques using PnP PowerShell and Microsoft Graph API.
What You'll Learn:
- Hub site architecture and benefits
- Planning hub site hierarchy and taxonomy
- Creating and configuring hub sites
- Associating sites and managing permissions
- Implementing shared navigation and branding
- Aggregating content across associated sites
- Hub site governance and lifecycle management
- Automation with PnP PowerShell and Graph API
- Migration strategies and best practices
Time to Complete: 90-120 minutes
Skill Level: Intermediate to Advanced
Hub Site Architecture
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SharePoint Hub Site Architecture β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Root Site Collection β
β (Tenant-wide Home) β
β β β
β ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β HR Hub β β Sales Hub β β IT Hub β β
β β (/hr) β β (/sales) β β (/it) β β
β ββββββββββββββββ€ ββββββββββββββββ€ ββββββββββββββββ€ β
β β Shared: β β Shared: β β Shared: β β
β β β’ Navigation β β β’ Navigation β β β’ Navigation β β
β β β’ Theme β β β’ Theme β β β’ Theme β β
β β β’ News β β β’ News β β β’ News β β
β β β’ Search β β β’ Search β β β’ Search β β
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββ¬ββββββββ β
β β β β β
β βββββββ΄ββββββ βββββββ΄ββββββ ββββββββ΄βββββββ β
β β β β β β β β
β βΌ βΌ βΌ βΌ βΌ βΌ β
β βββββββββ βββββββββ ββββββββ ββββββββ ββββββββββ βββββββββββ β
β β Bene β βRecruitβ βNorth β βSouth β βHelp β βProjects β β
β β fits β β ing β βRegionβ βRegionβ βDesk β β β β
β β Site β β Site β β Site β β Site β βSite β βSite β β
β βββββββββ βββββββββ ββββββββ ββββββββ ββββββββββ βββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Hub Site Capabilities β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β
β β β β
β β 1. Shared Navigation β β
β β ββ Top nav links appear on all associated sites β β
β β β β
β β 2. Unified Search Scope β β
β β ββ Search returns results from all associated sites β β
β β β β
β β 3. News Aggregation β β
β β ββ Hub home displays news from all associated sites β β
β β β β
β β 4. Consistent Branding β β
β β ββ Theme (colors, logo) inherited by associated sites β β
β β β β
β β 5. Metadata Inheritance β β
β β ββ Site columns available to associated sites β β
β β β β
β β 6. Permission Management β β
β β ββ Hub admins manage associations β β
β β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Benefits: β
β β Logical grouping of related sites β
β β Consistent user experience across departments β
β β Easier discovery of related content β
β β Simplified navigation and branding management β
β β Cross-site reporting and analytics β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Prerequisites
Required Licenses
- SharePoint Online (included in Microsoft 365 E3/E5)
- Microsoft 365 account with appropriate permissions
Required Permissions
- SharePoint Administrator or Global Administrator (to create hub sites)
- Hub Site Administrator (to manage associations)
- Site Owner (to associate sites with hub)
Required Tools
- PnP PowerShell Module
- SharePoint Online Management Shell
- Microsoft Graph PowerShell SDK (optional, for advanced automation)
Install Prerequisites
# Install PnP PowerShell (version 2.x - modern)
Install-Module -Name PnP.PowerShell -Scope CurrentUser -Force
# Verify installation
Get-Module PnP.PowerShell -ListAvailable
# Install SharePoint Online Management Shell
Install-Module -Name Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser -Force
# Install Microsoft Graph PowerShell (optional)
Install-Module Microsoft.Graph -Scope CurrentUser -Force
# Verify modules
Get-InstalledModule | Where-Object {$_.Name -like "*SharePoint*" -or $_.Name -like "*PnP*"}
Verify Permissions
# Connect to SharePoint Online
$tenantUrl = "https://contoso-admin.sharepoint.com"
Connect-PnPOnline -Url $tenantUrl -Interactive
# Check your roles
Get-PnPTenantSite | Select-Object Url, Owner, Template | Format-Table
# Verify hub site permissions
$currentUser = Get-PnPProperty -ClientObject (Get-PnPWeb) -Property CurrentUser
Write-Host "Current User: $($currentUser.LoginName)" -ForegroundColor Green
Write-Host "User Roles: $($currentUser.Groups)" -ForegroundColor Green
# Check if you can manage hub sites
try {
Get-PnPHubSite -ErrorAction Stop | Format-Table Title, SiteUrl
Write-Host "β You have hub site management permissions" -ForegroundColor Green
} catch {
Write-Host "β You need SharePoint Administrator role" -ForegroundColor Red
}
Step 1: Plan Your Hub Site Structure
Design Hub Site Hierarchy
Before creating hub sites, plan your information architecture:
Enterprise Hub Site Planning Matrix
ββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Hub Site β Associated Site Types β
ββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Corporate β β’ Company News β
β (/corporate) β β’ Executive Communications β
β β β’ Company Events β
β β β’ Employee Resources β
ββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β HR Hub β β’ Benefits β
β (/hr) β β’ Recruiting β
β β β’ Learning & Development β
β β β’ Employee Handbook β
ββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β IT Hub β β’ Help Desk β
β (/it) β β’ IT Policies β
β β β’ Software Downloads β
β β β’ Project Sites β
ββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Sales Hub β β’ Regional Sales Sites (North, South, East, West) β
β (/sales) β β’ Sales Enablement β
β β β’ Product Catalog β
β β β’ Customer Success β
ββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Finance Hub β β’ Financial Reports β
β (/finance) β β’ Expense Management β
β β β’ Procurement β
β β β’ Budget Planning β
ββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Hub Site Planning Worksheet
Create a planning document:
# Hub Site Planning: HR Department
**Hub Site Name**: Human Resources
**Hub Site URL**: https://contoso.sharepoint.com/sites/hr
**Hub Site Owner**: HR Director
**Hub Site Admins**: HR IT Team
## Purpose
Central hub for all HR-related sites, resources, and communications
## Associated Sites (Planned)
1. Benefits Site (/sites/hr-benefits)
2. Recruiting Site (/sites/hr-recruiting)
3. Learning & Development (/sites/hr-learning)
4. Employee Handbook (/sites/hr-handbook)
5. Onboarding (/sites/hr-onboarding)
## Shared Navigation Items
- Home
- Benefits
- Careers
- Learning
- Policies
- Contact HR
## Branding
- Primary Color: #0078D4 (Microsoft Blue)
- Secondary Color: #005A9E
- Logo: HR_Logo.png
- Header Background: hr_header_bg.jpg
## Metadata (Site Columns)
- Department (Choice: HR, IT, Finance, Sales)
- Document Type (Choice: Policy, Form, Guide, Report)
- Review Date (Date)
- Owner (Person)
## Governance
- Content Review: Quarterly
- Access Review: Annually
- Site Owners: Must complete training
- Retention: 7 years for policies, 3 years for general content
Step 2: Create Hub Sites
Create Hub Site via PnP PowerShell
# Connect to SharePoint Admin Center
$tenantUrl = "https://contoso-admin.sharepoint.com"
$tenantName = "contoso" # Your tenant name
Connect-PnPOnline -Url $tenantUrl -Interactive
# Create Communication Site (will become hub)
$hrSiteUrl = "https://$tenantName.sharepoint.com/sites/hr"
$hrSiteParams = @{
Type = "CommunicationSite"
Title = "Human Resources"
Url = $hrSiteUrl
Description = "Central hub for all HR resources and information"
Owner = "[email protected]"
SiteDesignId = "6142d2a0-63a5-4ba0-aede-d9fefca2c767" # Topic site design
Lcid = 1033 # English
HubSiteDesignId = "00000000-0000-0000-0000-000000000000" # Will be hub
}
Write-Host "Creating HR site..." -ForegroundColor Cyan
New-PnPSite @hrSiteParams
Write-Host "β Site created: $hrSiteUrl" -ForegroundColor Green
# Wait for site provisioning to complete
Start-Sleep -Seconds 30
# Register site as Hub Site
Write-Host "Registering as Hub Site..." -ForegroundColor Cyan
Register-PnPHubSite -Site $hrSiteUrl
Write-Host "β Hub Site registered" -ForegroundColor Green
# Verify hub site creation
$hubSite = Get-PnPHubSite -Identity $hrSiteUrl
Write-Host "`nHub Site Details:" -ForegroundColor Yellow
Write-Host " Title: $($hubSite.Title)"
Write-Host " URL: $($hubSite.SiteUrl)"
Write-Host " Hub Site ID: $($hubSite.ID)"
Create Multiple Hub Sites (Batch)
# Define all hub sites
$hubSites = @(
@{
Title = "Human Resources"
Url = "/sites/hr"
Description = "Central hub for all HR resources and information"
Owner = "[email protected]"
},
@{
Title = "Sales"
Url = "/sites/sales"
Description = "Sales enablement and regional coordination"
Owner = "[email protected]"
},
@{
Title = "Information Technology"
Url = "/sites/it"
Description = "IT services, projects, and documentation"
Owner = "[email protected]"
},
@{
Title = "Finance"
Url = "/sites/finance"
Description = "Financial reporting and budget management"
Owner = "[email protected]"
},
@{
Title = "Marketing"
Url = "/sites/marketing"
Description = "Marketing campaigns and brand resources"
Owner = "[email protected]"
}
)
# Create and register each hub site
foreach ($hub in $hubSites) {
$fullUrl = "https://$tenantName.sharepoint.com$($hub.Url)"
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
Write-Host "Creating Hub: $($hub.Title)" -ForegroundColor Cyan
Write-Host "βββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
try {
# Check if site already exists
$existingSite = Get-PnPTenantSite -Url $fullUrl -ErrorAction SilentlyContinue
if ($existingSite) {
Write-Host " β Site already exists: $fullUrl" -ForegroundColor Yellow
} else {
# Create site
$siteParams = @{
Type = "CommunicationSite"
Title = $hub.Title
Url = $fullUrl
Description = $hub.Description
Owner = $hub.Owner
Lcid = 1033
}
Write-Host " β Creating site..." -ForegroundColor Gray
New-PnPSite @siteParams
Start-Sleep -Seconds 20
Write-Host " β Site created" -ForegroundColor Green
}
# Check if already registered as hub
$existingHub = Get-PnPHubSite -Identity $fullUrl -ErrorAction SilentlyContinue
if ($existingHub) {
Write-Host " β Already registered as hub site" -ForegroundColor Yellow
} else {
# Register as hub site
Write-Host " β Registering as hub site..." -ForegroundColor Gray
Register-PnPHubSite -Site $fullUrl
Write-Host " β Hub site registered" -ForegroundColor Green
}
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Green
Write-Host "Hub Site Creation Complete!" -ForegroundColor Green
Write-Host "βββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Green
# List all hub sites
Write-Host "All Hub Sites:" -ForegroundColor Yellow
Get-PnPHubSite | Select-Object Title, SiteUrl, ID | Format-Table -AutoSize
Step 3: Configure Hub Site Settings
Set Hub Site Logo and Theme
# Connect to the HR hub site
$hrSiteUrl = "https://contoso.sharepoint.com/sites/hr"
Connect-PnPOnline -Url $hrSiteUrl -Interactive
# Upload logo
$logoPath = "C:\Logos\HR_Logo.png"
$logoFile = Add-PnPFile -Path $logoPath -Folder "SiteAssets" -Publish
Write-Host "β Logo uploaded: $($logoFile.ServerRelativeUrl)" -ForegroundColor Green
# Set site logo
$web = Get-PnPWeb
Set-PnPWeb -LogoUrl "$($web.ServerRelativeUrl)/SiteAssets/HR_Logo.png"
Write-Host "β Logo applied to hub site" -ForegroundColor Green
# Define custom theme
$themeJson = @"
{
"themePrimary": "#0078d4",
"themeLighterAlt": "#eff6fc",
"themeLighter": "#deecf9",
"themeLight": "#c7e0f4",
"themeTertiary": "#71afe5",
"themeSecondary": "#2b88d8",
"themeDarkAlt": "#106ebe",
"themeDark": "#005a9e",
"themeDarker": "#004578",
"neutralLighterAlt": "#faf9f8",
"neutralLighter": "#f3f2f1",
"neutralLight": "#edebe9",
"neutralQuaternaryAlt": "#e1dfdd",
"neutralQuaternary": "#d0d0d0",
"neutralTertiaryAlt": "#c8c6c4",
"neutralTertiary": "#a19f9d",
"neutralSecondary": "#605e5c",
"neutralPrimaryAlt": "#3b3a39",
"neutralPrimary": "#323130",
"neutralDark": "#201f1e",
"black": "#000000",
"white": "#ffffff"
}
"@
# Add custom theme to tenant
Connect-PnPOnline -Url "https://contoso-admin.sharepoint.com" -Interactive
Add-PnPTenantTheme -Identity "HR Theme" -Palette $themeJson -IsInverted $false -Overwrite
Write-Host "β Custom theme created" -ForegroundColor Green
# Apply theme to hub site
Connect-PnPOnline -Url $hrSiteUrl -Interactive
Set-PnPWebTheme -Theme "HR Theme"
Write-Host "β Theme applied to hub site" -ForegroundColor Green
Configure Hub Site Navigation
# Connect to hub site
Connect-PnPOnline -Url $hrSiteUrl -Interactive
# Clear existing navigation
Get-PnPNavigationNode -Location TopNavigationBar | Remove-PnPNavigationNode -Force
# Add hub navigation links
$navItems = @(
@{Title = "Home"; Url = "/sites/hr"},
@{Title = "Benefits"; Url = "/sites/hr-benefits"},
@{Title = "Careers"; Url = "/sites/hr-recruiting"},
@{Title = "Learning"; Url = "/sites/hr-learning"},
@{Title = "Policies"; Url = "/sites/hr-handbook"},
@{Title = "Contact HR"; Url = "/sites/hr/Pages/Contact.aspx"}
)
Write-Host "Adding navigation items..." -ForegroundColor Cyan
foreach ($item in $navItems) {
$fullUrl = "https://contoso.sharepoint.com$($item.Url)"
Add-PnPNavigationNode -Title $item.Title `
-Url $fullUrl `
-Location TopNavigationBar
Write-Host " β Added: $($item.Title)" -ForegroundColor Green
}
Write-Host "`nβ Navigation configured" -ForegroundColor Green
# Verify navigation
Get-PnPNavigationNode -Location TopNavigationBar |
Select-Object Title, Url |
Format-Table -AutoSize
Set Hub Site Permissions
# Connect to hub site
Connect-PnPOnline -Url $hrSiteUrl -Interactive
# Add hub site administrators
$hubAdmins = @(
"[email protected]",
"[email protected]",
"[email protected]"
)
Write-Host "Adding hub site administrators..." -ForegroundColor Cyan
foreach ($admin in $hubAdmins) {
try {
Add-PnPHubSiteAssociation -Site $hrSiteUrl -HubSiteAdmin $admin
Write-Host " β Added: $admin" -ForegroundColor Green
} catch {
Write-Host " β Failed to add: $admin" -ForegroundColor Red
Write-Host " Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
# Grant hub site permissions (for association)
Grant-PnPHubSiteRights -Identity $hrSiteUrl -Principals $hubAdmins -Rights Join
Write-Host "`nβ Hub administrators configured" -ForegroundColor Green
# List hub administrators
$hubSite = Get-PnPHubSite -Identity $hrSiteUrl
Write-Host "`nHub Administrators:" -ForegroundColor Yellow
$hubSite.SiteOwners | Format-Table
Step 4: Create and Associate Child Sites
Create Associated Sites
# Define associated sites for HR hub
$associatedSites = @(
@{
Title = "Benefits"
Url = "/sites/hr-benefits"
Description = "Employee benefits information and enrollment"
Owner = "[email protected]"
Template = "CommunicationSite"
},
@{
Title = "Recruiting"
Url = "/sites/hr-recruiting"
Description = "Talent acquisition and recruiting resources"
Owner = "[email protected]"
Template = "CommunicationSite"
},
@{
Title = "Learning & Development"
Url = "/sites/hr-learning"
Description = "Employee training and development programs"
Owner = "[email protected]"
Template = "CommunicationSite"
},
@{
Title = "Employee Handbook"
Url = "/sites/hr-handbook"
Description = "Company policies and employee guidelines"
Owner = "[email protected]"
Template = "CommunicationSite"
}
)
# Connect to tenant
Connect-PnPOnline -Url "https://contoso-admin.sharepoint.com" -Interactive
# Create each associated site
foreach ($site in $associatedSites) {
$fullUrl = "https://contoso.sharepoint.com$($site.Url)"
Write-Host "`nCreating: $($site.Title)" -ForegroundColor Cyan
try {
# Check if site exists
$existingSite = Get-PnPTenantSite -Url $fullUrl -ErrorAction SilentlyContinue
if ($existingSite) {
Write-Host " β Site already exists" -ForegroundColor Yellow
} else {
# Create site
$siteParams = @{
Type = $site.Template
Title = $site.Title
Url = $fullUrl
Description = $site.Description
Owner = $site.Owner
Lcid = 1033
}
New-PnPSite @siteParams
Write-Host " β Site created" -ForegroundColor Green
# Wait for provisioning
Start-Sleep -Seconds 15
}
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
Associate Sites with Hub
# Get hub site ID
$hrHubSite = Get-PnPHubSite -Identity "https://contoso.sharepoint.com/sites/hr"
$hrHubId = $hrHubSite.ID
Write-Host "Hub Site ID: $hrHubId" -ForegroundColor Yellow
Write-Host "`nAssociating sites with HR hub..." -ForegroundColor Cyan
foreach ($site in $associatedSites) {
$fullUrl = "https://contoso.sharepoint.com$($site.Url)"
try {
# Connect to the site
Connect-PnPOnline -Url $fullUrl -Interactive
# Associate with hub
Add-PnPHubSiteAssociation -Site $fullUrl -HubSite $hrHubId
Write-Host " β Associated: $($site.Title)" -ForegroundColor Green
} catch {
Write-Host " β Failed: $($site.Title)" -ForegroundColor Red
Write-Host " Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
Write-Host "`nβ All sites associated with hub" -ForegroundColor Green
# Verify associations
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/hr" -Interactive
$associatedSites = Get-PnPHubSiteChild -Identity $hrHubId
Write-Host "`nAssociated Sites:" -ForegroundColor Yellow
$associatedSites | Select-Object Title, Url | Format-Table -AutoSize
Bulk Associate Existing Sites
# Find all sites with specific naming pattern
$sitesToAssociate = Get-PnPTenantSite | Where-Object {
$_.Url -like "*/sites/hr-*" -and
$_.Template -eq "SITEPAGEPUBLISHING#0" # Communication site template
}
Write-Host "Found $($sitesToAssociate.Count) sites matching pattern" -ForegroundColor Yellow
foreach ($site in $sitesToAssociate) {
Write-Host "`nProcessing: $($site.Url)" -ForegroundColor Cyan
try {
# Check if already associated
Connect-PnPOnline -Url $site.Url -Interactive
$currentHub = (Get-PnPSite).HubSiteId
if ($currentHub -eq $hrHubId) {
Write-Host " β Already associated with HR hub" -ForegroundColor Yellow
} elseif ($currentHub -ne [guid]::Empty) {
Write-Host " β Already associated with another hub: $currentHub" -ForegroundColor Yellow
} else {
# Associate with hub
Add-PnPHubSiteAssociation -Site $site.Url -HubSite $hrHubId
Write-Host " β Successfully associated" -ForegroundColor Green
}
} catch {
Write-Host " β Error: $($_.Exception.Message)" -ForegroundColor Red
}
}
Step 5: Configure Aggregated Content
Create News Rollup on Hub Home
# Connect to hub site
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/hr" -Interactive
# Get or create homepage
$homePage = Get-PnPPage -Identity "Home.aspx" -ErrorAction SilentlyContinue
if (-not $homePage) {
$homePage = Add-PnPPage -Name "Home" -LayoutType Home -Publish
Write-Host "β Created homepage" -ForegroundColor Green
}
# Add News web part (aggregates from hub)
Add-PnPPageWebPart -Page $homePage `
-Component "News" `
-Section 1 `
-Column 1 `
-WebPartProperties @{
"dataProviderId" = "news"
"newsDataSourceProp" = 2 # 2 = Hub sites
"newsSiteList" = @() # Empty = all associated sites
"layoutId" = "FeaturedNews" # Featured news layout
"dataRowsLimit" = 10
}
Write-Host "β News rollup added to homepage" -ForegroundColor Green
# Add Events web part (aggregates from hub)
Add-PnPPageWebPart -Page $homePage `
-Component "Events" `
-Section 1 `
-Column 2 `
-WebPartProperties @{
"dataProviderId" = "events"
"eventsDataSource" = 2 # 2 = Hub sites
"layoutId" = "FilmStrip"
"dataRowsLimit" = 5
}
Write-Host "β Events rollup added to homepage" -ForegroundColor Green
# Add Highlighted Content (documents from hub)
Add-PnPPageWebPart -Page $homePage `
-Component "HighlightedContent" `
-Section 2 `
-Column 1 `
-WebPartProperties @{
"contentSource" = "hub" # Hub source
"queryMode" = "Basic"
"query" = @{
"contentTypes" = @("Document")
"sortBy" = "Modified"
"sortOrder" = "desc"
}
"layoutId" = "Card"
"dataRowsLimit" = 12
}
Write-Host "β Highlighted content added to homepage" -ForegroundColor Green
# Publish page
Set-PnPPage -Identity "Home.aspx" -Publish
Write-Host "`nβ Homepage published with aggregated content" -ForegroundColor Green
Create Custom Hub News Page
# Create dedicated news page
$newsPage = Add-PnPPage -Name "News" -LayoutType Article -Publish:$false
# Add page title section
Add-PnPPageTextPart -Page $newsPage -Text "# HR News & Updates" -Section 1 -Column 1
# Add News web part with filters
Add-PnPPageWebPart -Page $newsPage `
-Component "News" `
-Section 2 `
-Column 1 `
-WebPartProperties @{
"dataProviderId" = "news"
"newsDataSourceProp" = 2 # Hub sites
"layoutId" = "SideBySize"
"dataRowsLimit" = 20
"filterBy" = @{
"contentType" = "News"
}
}
# Publish news page
Set-PnPPage -Identity "News.aspx" -Publish
Write-Host "β Dedicated news page created" -ForegroundColor Green
# Add to navigation
Add-PnPNavigationNode -Title "News" `
-Url "/sites/hr/SitePages/News.aspx" `
-Location TopNavigationBar
Write-Host "β News page added to navigation" -ForegroundColor Green
Step 6: Implement Site Search Scope
Configure Hub Search Settings
# Connect to hub site
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/hr" -Interactive
# Create search schema (custom managed properties)
$searchConfig = @"
<SearchConfigurationSettings xmlns="http://schemas.datacontract.org/2004/07/Microsoft.Office.Server.Search.Administration.SearchConfigurationSettings">
<ManagedProperties>
<ManagedProperty>
<Name>HRDocumentType</Name>
<Type>Text</Type>
<RefinementFilters>
<RefinementFilter>Document</RefinementFilter>
<RefinementFilter>Policy</RefinementFilter>
<RefinementFilter>Form</RefinementFilter>
<RefinementFilter>Guide</RefinementFilter>
</RefinementFilters>
</ManagedProperty>
<ManagedProperty>
<Name>HRDepartment</Name>
<Type>Text</Type>
<RefinementFilters>
<RefinementFilter>Benefits</RefinementFilter>
<RefinementFilter>Recruiting</RefinementFilter>
<RefinementFilter>Learning</RefinementFilter>
<RefinementFilter>Compliance</RefinementFilter>
</RefinementFilters>
</ManagedProperty>
</ManagedProperties>
</SearchConfigurationSettings>
"@
# Import search configuration
Set-PnPSearchConfiguration -Scope Site -Configuration $searchConfig
Write-Host "β Search configuration imported" -ForegroundColor Green
# Create custom search results page
$searchPage = Add-PnPPage -Name "SearchResults" -LayoutType Article -Publish:$false
# Add Search Results web part
Add-PnPPageWebPart -Page $searchPage `
-Component "SearchResults" `
-Section 1 `
-Column 1 `
-WebPartProperties @{
"queryText" = "{searchTerms} path:https://contoso.sharepoint.com/sites/hr*"
"resultSourceId" = "8413cd39-2156-4e00-b54d-11efd9abdb89" # Local SharePoint Results
"refiners" = @{
"HRDocumentType" = @{
"displayName" = "Document Type"
"displayOrder" = 1
}
"HRDepartment" = @{
"displayName" = "Department"
"displayOrder" = 2
}
"FileType" = @{
"displayName" = "File Type"
"displayOrder" = 3
}
}
}
Set-PnPPage -Identity "SearchResults.aspx" -Publish
Write-Host "β Custom search results page created" -ForegroundColor Green
Step 7: Hub Site Governance
Create Hub Site Governance Policy
# Define governance metadata
$governanceMetadata = @{
"HubSiteOwner" = "[email protected]"
"HubSiteAdmins" = @("[email protected]", "[email protected]")
"ReviewFrequency" = "Quarterly"
"LastReview" = (Get-Date).ToString("yyyy-MM-dd")
"NextReview" = (Get-Date).AddDays(90).ToString("yyyy-MM-dd")
"RetentionPolicy" = "7 years for policies, 3 years for general content"
"AccessReviewFrequency" = "Annually"
"ComplianceRequirements" = @("GDPR", "SOX", "HIPAA")
}
# Connect to hub site
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/hr" -Interactive
# Store governance metadata as site properties
foreach ($key in $governanceMetadata.Keys) {
$value = if ($governanceMetadata[$key] -is [array]) {
$governanceMetadata[$key] -join ";"
} else {
$governanceMetadata[$key]
}
Set-PnPPropertyBagValue -Key "Governance_$key" -Value $value
Write-Host "β Set: $key = $value" -ForegroundColor Green
}
Write-Host "`nβ Governance metadata applied" -ForegroundColor Green
Monitor Hub Site Health
# Hub site health check script
function Get-HubSiteHealth {
param(
[string]$HubSiteUrl
)
Write-Host "`nββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
Write-Host "Hub Site Health Check: $HubSiteUrl" -ForegroundColor Cyan
Write-Host "ββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Cyan
try {
# Connect to hub site
Connect-PnPOnline -Url $HubSiteUrl -Interactive
# Get hub site details
$hub = Get-PnPHubSite -Identity $HubSiteUrl
$web = Get-PnPWeb
$site = Get-PnPSite
# Get associated sites
$associatedSites = Get-PnPHubSiteChild -Identity $hub.ID
# Calculate metrics
$metrics = @{
"Hub Site Title" = $hub.Title
"Hub Site URL" = $hub.SiteUrl
"Hub Site ID" = $hub.ID
"Associated Sites Count" = $associatedSites.Count
"Storage Used (GB)" = [math]::Round($site.StorageUsageCurrent / 1024, 2)
"Storage Quota (GB)" = [math]::Round($site.StorageMaximumLevel / 1024, 2)
"Storage % Used" = [math]::Round(($site.StorageUsageCurrent / $site.StorageMaximumLevel) * 100, 2)
"Last Modified" = $web.LastItemModifiedDate
"Site Owners" = ($hub.SiteOwners -join ", ")
}
# Display metrics
Write-Host "Hub Site Metrics:" -ForegroundColor Yellow
foreach ($key in $metrics.Keys) {
$color = if ($key -like "*% Used*" -and $metrics[$key] -gt 80) { "Red" } else { "White" }
Write-Host " $($key): $($metrics[$key])" -ForegroundColor $color
}
# Check for issues
Write-Host "`nHealth Checks:" -ForegroundColor Yellow
# Storage check
$storagePercent = ($site.StorageUsageCurrent / $site.StorageMaximumLevel) * 100
if ($storagePercent -gt 90) {
Write-Host " β CRITICAL: Storage usage > 90%" -ForegroundColor Red
} elseif ($storagePercent -gt 75) {
Write-Host " β WARNING: Storage usage > 75%" -ForegroundColor Yellow
} else {
Write-Host " β Storage usage OK" -ForegroundColor Green
}
# Associated sites check
if ($associatedSites.Count -eq 0) {
Write-Host " β WARNING: No associated sites" -ForegroundColor Yellow
} else {
Write-Host " β $($associatedSites.Count) sites associated" -ForegroundColor Green
}
# Navigation check
$navNodes = Get-PnPNavigationNode -Location TopNavigationBar
if ($navNodes.Count -eq 0) {
Write-Host " β WARNING: No navigation configured" -ForegroundColor Yellow
} else {
Write-Host " β $($navNodes.Count) navigation items configured" -ForegroundColor Green
}
# List associated sites
if ($associatedSites.Count -gt 0) {
Write-Host "`nAssociated Sites:" -ForegroundColor Yellow
$associatedSites | ForEach-Object {
Write-Host " β’ $($_.Title) ($($_.Url))" -ForegroundColor Gray
}
}
# Return metrics
return $metrics
} catch {
Write-Host "β Error checking hub site health: $($_.Exception.Message)" -ForegroundColor Red
return $null
}
}
# Run health check
$healthMetrics = Get-HubSiteHealth -HubSiteUrl "https://contoso.sharepoint.com/sites/hr"
# Export to CSV for reporting
if ($healthMetrics) {
$healthMetrics | Export-Csv -Path "HubSiteHealth_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
Write-Host "`nβ Health metrics exported to CSV" -ForegroundColor Green
}
Audit Hub Site Associations
# Audit all hub sites and their associations
function Get-HubSiteAudit {
$tenantUrl = "https://contoso-admin.sharepoint.com"
Connect-PnPOnline -Url $tenantUrl -Interactive
Write-Host "Auditing all hub sites..." -ForegroundColor Cyan
# Get all hub sites
$hubSites = Get-PnPHubSite
$auditReport = @()
foreach ($hub in $hubSites) {
Write-Host "`nProcessing: $($hub.Title)" -ForegroundColor Yellow
# Get associated sites
$associatedSites = Get-PnPHubSiteChild -Identity $hub.ID
# Get hub admins
Connect-PnPOnline -Url $hub.SiteUrl -Interactive
$site = Get-PnPSite
$owners = $site.Owner
# Create report entry
$reportEntry = [PSCustomObject]@{
HubTitle = $hub.Title
HubUrl = $hub.SiteUrl
HubID = $hub.ID
AssociatedSitesCount = $associatedSites.Count
AssociatedSites = ($associatedSites.Title -join "; ")
Owners = $owners.Email
LastModified = $site.LastContentModifiedDate
Status = if ($associatedSites.Count -eq 0) { "No Associations" } else { "Active" }
}
$auditReport += $reportEntry
Write-Host " Sites: $($associatedSites.Count)" -ForegroundColor Gray
}
# Export audit report
$reportPath = "HubSiteAudit_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$auditReport | Export-Csv -Path $reportPath -NoTypeInformation
Write-Host "`nβ Audit complete: $reportPath" -ForegroundColor Green
# Display summary
Write-Host "`nAudit Summary:" -ForegroundColor Yellow
Write-Host " Total Hub Sites: $($hubSites.Count)" -ForegroundColor White
Write-Host " Total Associated Sites: $(($auditReport | Measure-Object -Property AssociatedSitesCount -Sum).Sum)" -ForegroundColor White
Write-Host " Active Hubs: $(($auditReport | Where-Object {$_.Status -eq 'Active'}).Count)" -ForegroundColor Green
Write-Host " Inactive Hubs: $(($auditReport | Where-Object {$_.Status -eq 'No Associations'}).Count)" -ForegroundColor Yellow
return $auditReport
}
# Run audit
$auditReport = Get-HubSiteAudit
$auditReport | Format-Table -AutoSize
Step 8: Advanced Automation
Automate Hub Site Provisioning (Complete Solution)
# Complete hub site provisioning script
function New-CompleteHubSite {
param(
[Parameter(Mandatory=$true)]
[string]$HubTitle,
[Parameter(Mandatory=$true)]
[string]$HubUrl,
[Parameter(Mandatory=$true)]
[string]$Description,
[Parameter(Mandatory=$true)]
[string]$Owner,
[Parameter(Mandatory=$false)]
[string]$LogoUrl,
[Parameter(Mandatory=$false)]
[string]$ThemeName = "Default",
[Parameter(Mandatory=$false)]
[array]$NavigationItems = @(),
[Parameter(Mandatory=$false)]
[array]$AssociatedSites = @()
)
$tenantName = "contoso"
$fullHubUrl = "https://$tenantName.sharepoint.com$HubUrl"
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Cyan
Write-Host "Complete Hub Site Provisioning" -ForegroundColor Cyan
Write-Host "βββββββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Cyan
try {
# Step 1: Create Communication Site
Write-Host "Step 1: Creating communication site..." -ForegroundColor Yellow
Connect-PnPOnline -Url "https://$tenantName-admin.sharepoint.com" -Interactive
$siteParams = @{
Type = "CommunicationSite"
Title = $HubTitle
Url = $fullHubUrl
Description = $Description
Owner = $Owner
Lcid = 1033
}
New-PnPSite @siteParams
Write-Host " β Site created" -ForegroundColor Green
Start-Sleep -Seconds 20
# Step 2: Register as Hub Site
Write-Host "`nStep 2: Registering as hub site..." -ForegroundColor Yellow
Register-PnPHubSite -Site $fullHubUrl
Write-Host " β Hub site registered" -ForegroundColor Green
$hubSite = Get-PnPHubSite -Identity $fullHubUrl
$hubId = $hubSite.ID
Write-Host " Hub ID: $hubId" -ForegroundColor Gray
# Step 3: Configure site settings
Write-Host "`nStep 3: Configuring site settings..." -ForegroundColor Yellow
Connect-PnPOnline -Url $fullHubUrl -Interactive
# Apply theme
if ($ThemeName -ne "Default") {
Set-PnPWebTheme -Theme $ThemeName
Write-Host " β Theme applied: $ThemeName" -ForegroundColor Green
}
# Set logo
if ($LogoUrl) {
Set-PnPWeb -LogoUrl $LogoUrl
Write-Host " β Logo set" -ForegroundColor Green
}
# Step 4: Configure navigation
if ($NavigationItems.Count -gt 0) {
Write-Host "`nStep 4: Configuring navigation..." -ForegroundColor Yellow
# Clear existing navigation
Get-PnPNavigationNode -Location TopNavigationBar | Remove-PnPNavigationNode -Force
foreach ($navItem in $NavigationItems) {
Add-PnPNavigationNode -Title $navItem.Title `
-Url $navItem.Url `
-Location TopNavigationBar
Write-Host " β Added: $($navItem.Title)" -ForegroundColor Green
}
}
# Step 5: Create homepage with aggregated content
Write-Host "`nStep 5: Creating homepage..." -ForegroundColor Yellow
$homePage = Add-PnPPage -Name "Home" -LayoutType Home -Publish:$false
# Add hero web part
Add-PnPPageWebPart -Page $homePage -Component "Hero" -Section 1 -Column 1
# Add news rollup
Add-PnPPageWebPart -Page $homePage `
-Component "News" `
-Section 2 `
-Column 1 `
-WebPartProperties @{
"dataProviderId" = "news"
"newsDataSourceProp" = 2
"layoutId" = "FeaturedNews"
"dataRowsLimit" = 6
}
Set-PnPPage -Identity "Home.aspx" -Publish
Write-Host " β Homepage created with news rollup" -ForegroundColor Green
# Step 6: Associate sites
if ($AssociatedSites.Count -gt 0) {
Write-Host "`nStep 6: Associating sites..." -ForegroundColor Yellow
foreach ($siteUrl in $AssociatedSites) {
try {
Add-PnPHubSiteAssociation -Site $siteUrl -HubSite $hubId
Write-Host " β Associated: $siteUrl" -ForegroundColor Green
} catch {
Write-Host " β Failed: $siteUrl - $($_.Exception.Message)" -ForegroundColor Red
}
}
}
Write-Host "`nβββββββββββββββββββββββββββββββββββββββββββββ" -ForegroundColor Green
Write-Host "β Hub Site Provisioning Complete!" -ForegroundColor Green
Write-Host "βββββββββββββββββββββββββββββββββββββββββββββ`n" -ForegroundColor Green
Write-Host "Hub Site Details:" -ForegroundColor Yellow
Write-Host " Title: $HubTitle" -ForegroundColor White
Write-Host " URL: $fullHubUrl" -ForegroundColor White
Write-Host " Hub ID: $hubId" -ForegroundColor White
Write-Host " Associated Sites: $($AssociatedSites.Count)" -ForegroundColor White
return @{
Success = $true
HubUrl = $fullHubUrl
HubId = $hubId
}
} catch {
Write-Host "`nβ Error during provisioning: $($_.Exception.Message)" -ForegroundColor Red
return @{
Success = $false
Error = $_.Exception.Message
}
}
}
# Example: Provision complete HR hub
$hrHubConfig = @{
HubTitle = "Human Resources"
HubUrl = "/sites/hr"
Description = "Central hub for all HR resources and information"
Owner = "[email protected]"
LogoUrl = "/sites/hr/SiteAssets/HR_Logo.png"
ThemeName = "HR Theme"
NavigationItems = @(
@{Title = "Home"; Url = "/sites/hr"},
@{Title = "Benefits"; Url = "/sites/hr-benefits"},
@{Title = "Careers"; Url = "/sites/hr-recruiting"},
@{Title = "Learning"; Url = "/sites/hr-learning"},
@{Title = "Policies"; Url = "/sites/hr-handbook"}
)
AssociatedSites = @(
"https://contoso.sharepoint.com/sites/hr-benefits",
"https://contoso.sharepoint.com/sites/hr-recruiting",
"https://contoso.sharepoint.com/sites/hr-learning",
"https://contoso.sharepoint.com/sites/hr-handbook"
)
}
$result = New-CompleteHubSite @hrHubConfig
if ($result.Success) {
Write-Host "`nβ Hub site ready: $($result.HubUrl)" -ForegroundColor Green
} else {
Write-Host "`nβ Provisioning failed: $($result.Error)" -ForegroundColor Red
}
Best Practices Summary
DO:
- β Plan hub site hierarchy before implementation
- β Use semantic URLs (/sites/department-name)
- β Limit hub sites (5-15 per tenant typically)
- β Apply consistent branding across hubs
- β Configure shared navigation early
- β Set up news aggregation on hub homes
- β Document governance and ownership
- β Monitor hub site health regularly
- β Train site owners on hub concepts
- β Use PnP PowerShell for automation
DON'T:
- β Create too many hub sites (causes confusion)
- β Associate sites with multiple hubs
- β Skip permission planning
- β Forget to configure search scope
- β Ignore governance and lifecycle management
- β Over-nest hub hierarchies (keep flat)
- β Use hub sites for temporary projects
- β Skip training for site owners
- β Neglect regular audits
- β Hard-code URLs in navigation
Key Takeaways
- Hub sites connect your intranet - Unified navigation, search, and branding across related sites
- Planning is critical - Map your org structure to hub architecture before building
- Governance ensures success - Define ownership, review cycles, and compliance requirements
- Automation scales deployment - PnP PowerShell enables enterprise-wide provisioning
- Aggregated content drives engagement - News rollups and events keep users informed
- Permissions matter - Hub admins control associations, site owners manage content
- Monitoring prevents issues - Regular health checks identify problems early
- Search scope unifies discovery - Users find content across all associated sites
- Branding creates consistency - Shared themes and navigation improve UX
- Documentation drives adoption - Clear governance and training accelerate usage
Additional Resources
- SharePoint Hub Sites Overview
- PnP PowerShell Hub Site Cmdlets
- Hub Site Planning Guide
- SharePoint Online Limits
- Microsoft 365 Learning Pathways
Next Steps
- Assess current structure: Map existing sites to logical hubs
- Create pilot hub: Start with one department (e.g., HR or IT)
- Define governance: Document policies, owners, and review cycles
- Automate provisioning: Build PowerShell scripts for consistency
- Train site owners: Conduct workshops on hub site concepts
- Roll out incrementally: Deploy one hub at a time, gather feedback
- Monitor and optimize: Use health checks and audits to improve
- Scale across organization: Apply learnings to remaining departments
Ready to unify your SharePoint environment? Start with a pilot hub site for your most mature departmentβyou'll immediately see the benefits of connected navigation and aggregated content!