Showing posts with label SharePoint. Show all posts
Showing posts with label SharePoint. Show all posts

May 7, 2026

Building Site-Aware Enterprise AI Agents on Microsoft 365 Using Claude Agent SDK

Introduction

An enterprise running seven department-specific SharePoint intranet sites needed AI that could actually operate within their systems - not just answer questions about them. Here is what a single task looked like before we got involved - and after.

Before - Sales proposal workflow After - same task, one sentence
Open Pipeline Tracker on SharePoint - find the deal Type: "Draft a proposal for XYZ Corp's cloud migration deal and send it to their CTO."
Switch to Client Contacts - find the CTO's email Agent queries Pipeline Tracker - pulls deal value, stage, scope notes
Open Word - hunt for the proposal template on the shared drive Agent looks up CTO in Client Contacts - name, email, title
Manually fill in deal value, scope, and terms Branded proposal generated from python-docx template and uploaded to Sales Collateral
Save, switch back to SharePoint, upload to Sales Collateral library Email compose panel opens - pre-filled with CTO's address, subject, and body
Open Outlook - type the CTO's email, write the body, attach, send Review, tweak one line, hit Send
40 minutes  ·  6 applications  ·  1 task One sentence  ·  Five systems  ·  Done

We assessed the organisation's requirements against Copilot Cowork and Claude Cowork. Both are genuinely capable products - but neither could query custom SharePoint list schemas, connect to a SQL employee database, generate documents from branded templates, or switch to a different specialist persona depending on which department site the user was on. They needed something those products are structurally not built to do.

Same panel. Same backend. Same LLM. Completely different specialist per site, loaded at runtime from a JSON manifest. This is what we built. Here is how:

The Architecture in One Sentence

A single SPFx floating panel on every SharePoint page sends messages to a FastAPI backend, which enters a Claude agentic loop with a filtered set of MCP tools - filtered by which site the user is on, what they are allowed to do, and which department's data model applies. Each site loads its own agent persona, slash commands, and skill files - deep knowledge modules that teach the agent how a specific department's data is structured, what business rules apply, and which workflows exist.

System Architecture diagram

System Architecture - SPFx panel → FastAPI backend → Claude agentic loop → MCP server → enterprise data sources

That sentence hides a lot of machinery. Three decisions do most of the work: how each site loads its own specialist, how authentication is split between reads and writes, and how the agentic loop orchestrates everything in between. Let me walk through each.

Decision 1: The Plugin Manifest

When a user opens the Sales site and the panel initialises, the backend resolves their session: who are they (from the OBO token), which site are they on (from the site_url passed by the frontend), and what can they do (from the plugin manifest). The manifest is a single JSON file:

{
  "name": "sales",
  "display_name": "Sales Assistant",
  "entry_agent": "agents/sales-assistant.md",
  "connectors": ["sharepoint", "msgraph", "email", "docgen", "ems",
    "knowledge", "analytics", "automation"],
  "commands": ["commands/pipeline-report.md", "commands/add-lead.md", ...],
  "skills": ["skills/pipeline-management/SKILL.md",
    "skills/client-engagement/SKILL.md", ...],
  "sharepoint_lists": {
    "lists": {
      "Pipeline Tracker": "columns: OpportunityName, DealValue, PipelineStage, ..."
    }
  }
}

This manifest does five things at session start:

It loads a persona.

The entry_agent points to a markdown file that defines the agent's personality, role, behaviour rules, and domain expertise. The Sales agent is "friendly, professional, and results-driven." The Finance agent is precise and compliance-aware. The People agent is warm and policy-oriented. Same LLM, different specialist.

It filters the tool palette.

The connectors array controls which of the 58 MCP tools appear in Claude's tool list for this session. Sales gets SharePoint, Graph, Email, DocGen, EMS, Knowledge, Analytics, and Automation - but not Azure DevOps. Delivery gets Azure DevOps too. Technology gets everything. The LLM only sees tools it is allowed to use.

It loads skill files.

This is where the deep domain knowledge lives. Each skill is a markdown file that describes how a specific aspect of the department works. The Sales plugin has skills for pipeline management, client engagement, and competitive intelligence. A skill might describe how the Pipeline Tracker list is structured, what each column means, which OData filters produce useful results, what "stalled deal" means in this organisation's context, and what steps the agent should follow for a pipeline review. Skills are loaded into the system prompt based on the site and the user's query - they are the agent's domain training, delivered at runtime through text, not fine-tuning.

It injects list schemas.

The sharepoint_lists block is injected into the system prompt. This is how the agent knows the column is called PipelineStage, not Stage. It knows DealValue is the field for revenue, not Value or Amount. It never guesses. If a column is not in the manifest, the agent cannot reference it.

It registers slash commands.

Each command is a markdown file with trigger phrases, required parameters, the agent to hand off to, and step-by-step instructions. When a user types /pipeline-report, the command's markdown gets injected into the system prompt for that turn.

Plugin-Per-Site Architecture diagram

Plugin-Per-Site Architecture - 7 sites, auto-discovered, manifest-driven, session-filtered

The consequence of this design is that adding a new department - an eighth site, a regional hub, a project workspace - requires creating one folder with one JSON manifest and a few markdown files. No code changes. No backend redeployment. The registry discovers it on next restart.

The key insight: The plugin folder is the architecture. Not the LLM, not the framework, not the cloud infrastructure. The entire system's behaviour - which specialist responds, which tools are available, which data is accessible, which commands exist, which domain knowledge the agent draws on - is determined by which plugin.json file gets loaded and which skill files sit alongside it. Everything else is shared plumbing. This is what makes the system maintainable at scale: changing a department's AI behaviour is editing a JSON file and a few markdown documents, not shipping code.

Decision 2: Dual-Auth and the Invisible Session

Authentication is where most custom AI implementations get it wrong. Either they use the user's token for everything (writes are unauditable and tied to individual permissions) or they use an app-only token for everything (losing the identity context of who asked for the action).

We split it:

Reads use the user's delegated OBO token.

When the agent queries a SharePoint list or fetches calendar events, it does so as the user. If the user cannot see a site, neither can the agent. The existing M365 permission model is preserved - no data leakage, no privilege escalation.

Writes use an app-only certificate token.

  • All write operations - list item creation, document upload, email send - execute through a controlled service identity, not the user's token.
  • Every write is routed through an audit logger: who requested it, what changed, tool name, payload, status, and duration.
  • site_url, OBO token, app-only token, and the user's permission set are never parameters the LLM sees - they are injected from the session object before the agentic loop begins.

In the initial version, SharePoint tools accepted site_url as a tool parameter. During early integration testing, Claude hallucinated a URL - it substituted the Sales site URL when a user on the Finance site asked about budget items. The query returned nothing. The agent confidently reported "no budget items found." It was a silent, plausible failure - the worst kind. We refactored site_url out of every tool interface within the day and moved it to session-level injection. The LLM never sees it, never chooses it, never hallucinates it.

If the LLM does not need a value to reason about the task, do not put it in the tool interface. Every parameter visible to the LLM is a surface for hallucination. Session-level injection eliminates that surface.

Decision 3: The Agentic Loop

When a user sends a message, the backend does not call Claude once and return the answer. It enters a loop:

Agentic Loop diagram

Agentic Loop - Request Lifecycle with tool execution feedback loop

  • Multi-step tool chains. A single message like "find stalled deals, draft follow-ups, and notify the sales lead" triggers five sequential tool calls - SharePoint OData query, EMS employee lookup, three email draft preparations - each feeding the next decision.
  • Real-time status streaming. Each tool call emits an SSE event to the frontend ("Fetching list data: Pipeline Tracker...", "Looking up employee...") so the user sees the agent working, not a loading spinner.
  • Model is a config variable. Claude Sonnet is the default - fast enough for real-time streaming, capable enough for multi-step orchestration. Swapping models is a single environment variable change; the architecture is not coupled to any provider.
  • We tested Azure OpenAI + Semantic Kernel. The loop runs and tools get called. But in head-to-head testing, Claude produced fewer hallucinated tool parameters, followed complex multi-step prompts more faithfully, and handled branching logic - where a tool result determines whether to call the next tool or skip to a different action - more consistently. That is why it is our default.

What the Agent Can Actually Do

58 tools across 9 connectors. Here are the ones that matter most to daily operations:

Connector What it does Available on
SharePoint Read list items with OData filters, create and update items, browse document libraries, upload files, search across the site. Primary data layer. All sites
EMS Direct SQL via pyodbc against the HR database: employee lookup, org chart traversal, leave balances, skills search, project assignments, team allocation, capacity planning, budget tracking. No REST wrapper. All sites
Document generation Branded offer letters, proposals, and reports via python-docx. Budget workbooks via openpyxl. Generated on the backend, uploaded to SharePoint, download card in chat. Sales, People, Finance, Operations
Email Two-step workflow: agent drafts, human reviews in inline compose panel, then confirms Send. Never auto-sends. All sites
Azure DevOps Query and create work items, get sprint status. Delivery, Technology only
Proactive alerts Five APScheduler handlers: stalled deals, budget thresholds, expiring contracts, onboarding gaps, morning brief digest. Push to Teams channels and notification bell before anyone opens a browser. All sites (handler-specific)
MS Graph Users, calendar, Teams channels, mail integration. All sites
Analytics Natural language reports, anomaly detection. All sites
Knowledge Federated search, expert finder. All sites

Lessons from the Build

Every implementation surfaces lessons that inform the next one.

SharePoint field name complexity runs deeper than expected.

Display names and internal names diverge in non-obvious ways. "Status" might be stored as BudgetStatus. "Details" might be AnnouncementDetails. The initial deployment surfaced field name mismatches that cost debugging cycles. Our fix - a PowerShell schema export script that generates verified field mappings per site - is now a standard first step in our deployment methodology.

Not every data source needs an API layer.

Our first design had a full REST API wrapper around the SQL employee database. We replaced it with direct pyodbc queries wrapped in the MCP tool contract. Simpler, faster, easier to maintain.

The in-process MCP server will need extraction.

Running the tool server in-process was the right call for initial development - no serialisation overhead, easy debugging. But for production scale, tool execution needs to run independently so long-running operations (document generation, cross-site searches) do not block the API layer. The architecture was designed for this extraction - MCP's HTTP transport makes it a configuration change, not a rewrite - which is planned for the next phase.

Retry logic is now day-one infrastructure.

Claude's API occasionally returns transient errors under load. Without exponential backoff (1s, 2s, 4s), these surface as user-facing failures. Retry logic is now part of our standard agentic infrastructure from the start, based on this experience.

Production hardening - monitoring, observability, error recovery, and scale testing - deserves its own post. We will publish that next.

A Note on Portability

This case study uses SharePoint as the enterprise platform and Claude as the LLM, but the pattern is platform-agnostic. The same plugin-per-site architecture has been applied with Confluence, custom intranets, and internal portals. The frontend can be any web surface that supports a JavaScript embed - the SPFx panel is one implementation, not a requirement. The connectors, the plugin manifest pattern, the dual-auth model, and the session-scoped tool filtering are all transferable. If your organisation runs on a different stack, the architecture adapts to it.

Conclusion

The plugin-per-site pattern, dual-auth model, session-scoped tool filtering, and in-process MCP server described here form a reusable enterprise architecture - not a one-off implementation. Adding a new department means creating a folder with a JSON manifest and a few markdown skill files. No code changes, no redeployment. The system's behaviour is entirely determined by configuration, not by the codebase.

This architecture was designed and deployed by Binary Republik. It is adaptable to any organisation's departmental structure, data model, and governance requirements - and transferable to any enterprise platform with programmatic APIs.

If you have any questions you can reach out to our AI Consulting team here.

April 27, 2026

How to Lock Down SharePoint Access with Sites.Selected Permissions

Introduction

If you've ever granted an app Sites.ReadWrite.All permissions in SharePoint, you know that sinking feeling you've just given it the keys to every single site in your tenant. For most applications, that's like using a sledgehammer to hang a picture frame.

There's a better way: Sites.Selected permissions. This feature lets you grant your application access to only the specific SharePoint sites it actually needs nothing more, nothing less. It's the principle of least privilege in action, and it's surprisingly straightforward to set up.

In this guide, I'll walk you through the complete process of configuring Sites.Selected with read-only access to a specific SharePoint site. We'll use Microsoft Graph Explorer (no PowerShell required), and by the end, you'll have a secure, properly scoped application that can only access the data it needs.

What Is Sites.Selected and Why Should You Care?

Sites.Selected is a Microsoft Graph permission that flips the traditional access model on its head. Instead of granting tenant-wide access upfront, you start with zero access and explicitly grant permissions to individual sites as needed.

Think of it this way:

  • Sites.ReadWrite.All = Master key to every door in the building
  • Sites.Selected = Specific key cards for only the rooms you need

This approach drastically reduces your attack surface. If your application's credentials are ever compromised, the blast radius is limited to just the sites you've explicitly granted access to not your entire SharePoint environment.

The Three-Phase Process

Setting up Sites.Selected permissions involves three distinct phases, each building on the last:

Phase Action Where
1 Create app registration & add Sites.Selected permission Azure Portal
2 Get SharePoint site ID Microsoft Graph Explorer
3 Grant read permission to site Microsoft Graph Explorer

Here's the crucial thing to understand: after Phase 1, your app has Sites.Selected consent but zero actual access. It's not until Phase 3 that you grant permission to specific sites. This two-step process is what makes the permission model secure.

What You'll Need

Before we dive in, make sure you have:

  • Global Admin or Application Admin role in Azure AD
  • SharePoint Admin access
  • The URL of the SharePoint site you want to grant access to

That's it. No PowerShell modules to install, no scripts to run just your browser and admin credentials.

Phase 1: Creating Your App Registration

The first phase happens entirely in the Azure Portal. We'll create a new app registration and add the Sites.Selected permission but remember, this doesn't grant access to anything yet.

Navigate to App Registrations

Head to https://portal.azure.com and sign in with your admin account. Use the search bar at the top to find App registrations and select it.

Register Your Application

Click + New registration and fill in these details:

Field Value
Name SharePoint-Reader-App
Supported account types Accounts in this organizational directory only
Redirect URI Leave blank

Click Register and you'll land on the app overview page.

Save Your Application ID

On the overview page, you'll see an Application (client) ID. This is a GUID that looks something like a3f44e63-e46e-4c31-9213-888c172ca160. Copy this and save it somewhere safe you'll need it in Phase 3.

Add the Sites.Selected Permission

In the left menu, click API permissions, then + Add a permission. Here's where it gets specific:

  1. Select Microsoft Graph
  2. Choose Application permissions (not Delegated this is critical)
  3. Search for Sites.Selected
  4. Check the box and click Add permissions

Application permissions are for background services and daemon apps that run without a signed-in user. Delegated permissions are for apps that act on behalf of a user. For Sites.Selected to work, you must use Application permissions.

Grant Admin Consent

Back on the API permissions page, click Grant admin consent for [Your Organization] and confirm. You'll see a green checkmark appear next to Sites.Selected with a status of Granted.

Important: At this point, your app has Sites.Selected consent, but it still can't access any sites. That's by design. Phase 3 is where you grant the actual site-level permissions.

Phase 2: Getting the SharePoint Site ID

To grant permissions to a specific site, you need its Site ID. This is a long, comma-separated string that uniquely identifies the site in your tenant. We'll use Microsoft Graph Explorer to retrieve it.

Open Graph Explorer and Sign In

Navigate to https://developer.microsoft.com/en-us/graph/graph-explorer and click Sign in to Graph Explorer in the top right. Use your admin account.

Consent to Permissions (Critical Step)

Here's something that trips people up: Graph Explorer needs its own permissions to make API calls. These are separate from your app's permissions.

Click the Modify permissions tab below the query box. Find these two permissions and consent to both:

  • Sites.Read.All (needed to retrieve the site ID)
  • Sites.FullControl.All (needed in Phase 3 to grant permissions)

For each permission, click Consent, then Accept in the pop-up. Verify both show a Consented status before proceeding.

Construct Your Query

Set the method dropdown to GET. Now you need to build the URL. The format is:

https://graph.microsoft.com/v1.0/sites/{tenant}.sharepoint.com:/sites/{sitename}

Let's say your site is https://contoso.sharepoint.com/sites/ProjectAlpha. Your Graph API URL would be:

https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/ProjectAlpha

Note: Use the site name from the URL, not the display name. If your site is called "Project Alpha Site" but the URL is ProjectAlpha, use ProjectAlpha.

Run the Query and Extract the Site ID

Click Run query. In the Response preview, you'll see JSON that looks like this:

{
  "id": "contoso.sharepoint.com,a1b2c3d4-1234-5678-abcd-111122223333,e5f6g7h8-4321-8765-dcba-444455556666",
  "name": "ProjectAlpha",
  "displayName": "Project Alpha",
  "webUrl": "https://contoso.sharepoint.com/sites/ProjectAlpha"
}

Copy the entire id value the whole thing, including the commas. This is your Site ID. Save it alongside your Application ID.

The Site ID format is {hostname},{site-collection-id},{web-id}. Don't try to reconstruct it manually or use just part of it you need the complete string.

Phase 3: Granting Read Permission to Your Site

This is where everything comes together. We'll use a POST request in Graph Explorer to grant your application read access to the specific site.

Set Up the POST Request

In Graph Explorer, change the method to POST. The URL format is:

https://graph.microsoft.com/v1.0/sites/{siteId}/permissions

Replace {siteId} with the full Site ID you copied in Phase 2. For our example:

https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com,a1b2c3d4-1234-5678-abcd-111122223333,e5f6g7h8-4321-8765-dcba-444455556666/permissions

Add the Request Body

Click the Request body tab and enter this JSON:

{
  "roles": ["read"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "YOUR-APPLICATION-CLIENT-ID",
        "displayName": "SharePoint-Reader-App"
      }
    }
  ]
}

Critical: Replace YOUR-APPLICATION-CLIENT-ID with the Application ID you saved in Phase 1. Using our example ID, the complete JSON would be:

{
  "roles": ["read"],
  "grantedToIdentities": [
    {
      "application": {
        "id": "a3f44e63-e46e-4c31-9213-888c172ca160",
        "displayName": "SharePoint-Reader-App"
      }
    }
  ]
}

The roles array specifies the permission level. We're using read for read-only access. Other options include write, manage, and fullcontrol.

Execute and Verify

Click Run query. If everything is configured correctly, you'll receive a 201 Created response with JSON that looks like:

{
  "id": "aTowaS50fG1zLnNwLmV4dHxlYTVmMDVlZ...",
  "roles": ["read"],
  "grantedToIdentitiesV2": [...],
  "grantedToIdentities": [...]
}

That id field in the response is the permission ID. Save it if you think you might need to update or revoke this permission later.

Verifying Everything Works

To confirm the permission was granted successfully, you can query the permissions endpoint. Change the method back to GET and use:

https://graph.microsoft.com/v1.0/sites/{siteId}/permissions

Click Run query. You should see your application listed in the response with roles set to ["read"].

Understanding Available Permission Roles

We used read in this guide, but Sites.Selected supports four permission levels:

Role Description
read Read-only access (used in this guide)
write Read and write access
manage Manage lists and libraries
fullcontrol Full control over the site

Choose the most restrictive role that meets your application's needs. If you only need to read documents, stick with read.

Common Issues and How to Fix Them

Here are the most common problems people run into and their solutions:

403 Forbidden Error

If you get a 403 error when trying to grant permissions in Phase 3, you likely haven't consented to Sites.FullControl.All in Graph Explorer. Go back to the Modify permissions tab and consent to it.

Site Not Found

Double-check that you're using the site name from the URL, not the display name. If your site URL is /sites/proj-alpha but the display name is Project Alpha Team Site, use proj-alpha.

Insufficient Privileges

Make sure you've clicked Modify permissions in Graph Explorer and consented to both Sites.Read.All and Sites.FullControl.All. These are Graph Explorer's permissions, not your app's.

Invalid Request Body

Check your JSON syntax carefully. Common mistakes include missing commas, mismatched brackets, or forgetting to replace YOUR-APPLICATION-CLIENT-ID with your actual Application ID.

Wrapping Up

Sites.Selected permissions represent a massive improvement in security posture for SharePoint integrations. Instead of granting blanket access to your entire tenant, you can scope applications down to exactly what they need and nothing more.

The process involves three phases: creating an app registration with Sites.Selected consent in Azure Portal, retrieving the Site ID using Graph Explorer, and granting site-specific permissions via a POST request. Each phase builds on the last, and by the end, you have a properly scoped application that follows the principle of least privilege.

If you're building SharePoint integrations, this should be your default approach.

If you have any questions you can reach out our SharePoint Consulting team here.

November 20, 2025

Step-by-Step Guide: Convert a SharePoint Site Page to PDF using Power Automate

Converting SharePoint site pages into PDFs can be useful for creating reports, archives, or offline documentation. In this step-by-step guide, we’ll walk through how to automate this process using Power Automate.

Step 1: Create a Power Automate Flow

Start by creating a new Power Automate flow.
You can trigger it manually or configure it to run on a schedule or in response to a specific event, depending on your requirements.

Step 2: Initialise Department Variable

Add an Initialise Variable action to store the department name.
This variable will be used later when creating folders inside your document library.

Step 3: Initialise PDF File Name Variable

Next, create another Initialise Variable to hold the PDF file name that will be generated for each site page.


Step 4: Get Site Pages

Add a Get Files (Properties Only) action and point it to your Site Pages library.
You can apply a Filter Query to limit the results, or leave it blank to fetch all site pages.


Step 5: Apply to Each Site Page

Insert an Apply to Each loop and select the value output from the previous “Get Files” action.


Step 6: Set Department Variable

Inside the loop, set the Department variable using the value from your DepartOwner (or equivalent) column from the “Get Files” action.


💡 Replace the column name if your field name differs.

Step 7: Set PDF File Name Variable

Now, set the PDF file name dynamically using the page title:
concat(items('Apply_to_each')?['Title'], '.pdf')

Step 8: Get Canvas Content from Site Page

Add a Send an HTTP Request to SharePoint action.
Use it to retrieve the canvas content of each site page.
Pass the ID of the page from the “Get Files” action to get its content.


Step 9: Parse Canvas Content

Add a Parse JSON action to interpret the response from the previous HTTP request.
Use the Body output from the “Send an HTTP Request to SharePoint” step.


Step 10: Create a Temporary HTML File in OneDrive

Next, add a Create File action (in OneDrive).
This will temporarily store the HTML version of the site page.


File Name: concat(items('Apply_to_each')?['Title'], '.html')

Step 11: Convert HTML to PDF

Use the Convert File action (OneDrive) to convert the HTML file into a PDF.
Pass the File ID from the previous “Create File” step.

Step 12: Create a Folder in SharePoint

Add a Create New Folder action in your SharePoint Document Library.
Set the Folder Path using your Department variable to organise PDFs by department.


Step 13: Upload the PDF to SharePoint

Add a Create File (SharePoint) action.
This will create the final PDF inside the folder created in the previous step.


Step 14: Delete Temporary HTML File

Finally, clean up the temporary HTML file created in OneDrive.
Add a Delete File (OneDrive) action and pass the File ID from the earlier “Create File” step.



Once your flow is complete, run it manually (or trigger it automatically as configured). Your SharePoint site pages will now be converted into well-organised PDF files stored neatly in your document library.

If you have any questions you can reach out our SharePoint Consulting team here.

July 24, 2025

Modern SharePoint - Creating Site Pages with Section Templates and Real-Time Previews

Introduction:

SharePoint has long been a cornerstone for businesses looking to manage content and collaborate effectively. With its user-friendly interface and out-of-the-box features, SharePoint enables users to create dynamic, engaging web pages with minimal technical knowledge. The Modern SharePoint experience has taken this a step further with new features like Section Templates, which allow you to create visually consistent pages without needing to start from scratch.

These templates not only save time but also ensure your pages are visually appealing, structured, and aligned with your brand's identity. SharePoint’s recent updates bring even more flexibility and real-time feedback to the content creation process, empowering users to build professional, polished pages.

In this blog, we’ll dive deep into how you can leverage Section Templates, customize section properties, and make the most of real-time previews to build dynamic pages that are ready for publication - without the need to save or publish.


Step-by-Step Guide to Using SharePoint Modern Page Templates and Section Templates:

1. Navigating to the Page Editor:

To get started, head to the Site Content section of your SharePoint site. From here:

  • Click on ‘New’ and select ‘Page’. This action will open the Page Editor. 


2. Accessing Section Templates:

  • Once you’re inside the page editor, on the right-side pane, you’ll find the ‘Section Templates’ option. Click on ‘See All Section Templates’ at the bottom to view a comprehensive list of pre-designed templates.
section templates 

  • These templates are organized based on the content type and layout, making it easy to choose one that fits your needs.

3. Selecting and Customizing Your Template:

SharePoint gives you the ability to browse and select from a wide variety of templates. Once you pick one that fits your page’s needs, you can start customizing it to fit your brand’s style. You can:

  • Modify text and images
  • Change the layout and section arrangement

This allows you to design pages without needing to start from scratch, which is especially useful for non-developers or anyone looking to save time.

4. Customizing Section Properties:

Once you’ve chosen your template, you can further customize individual sections to suit your specific needs. SharePoint allows you to modify several properties for each section, including:

  • Collapsible Sections: You can make sections collapsible to save space and control how much content is visible. This is especially useful for pages with a lot of information.
  • Heading Levels: Customize the heading structure for better hierarchy and readability.
  • Divider Lines: Use divider lines to create separation between sections for a cleaner, more organized look.
  • Alignment Options: Control the alignment of content within each section (e.g., left or right alignment for expand/collapse icons).
  • Mobile and Email Reflow: Adjust how content reflows on mobile devices or in email formats (top to bottom, left to right). This ensures a seamless experience across all devices.
section properties

By customizing these properties, you can fine-tune the page layout and user experience, all while maintaining flexibility for different content types.

5. Previewing the Changes:

One of the best features of SharePoint’s page editor is the Preview function. You can see how your page will look across devices (desktop, tablet, mobile) in real time. This means you can:

  • Make adjustments without having to publish the page first.
  • Fine-tune the layout to make sure it’s perfect across different screen sizes.
CMS

This feature eliminates the guesswork that typically comes with designing web pages, ensuring your page looks great before it’s live.

6. Saving and Publishing Your Page:

Once you’ve customized the template, previewed your changes, and are happy with the result, it’s time to save and publish your page. SharePoint makes this process as easy as clicking a button, allowing you to get your content online quickly.


Benefits of Using Modern Section Templates and Real-Time Previews in SharePoint:

1. Time Efficiency:

  • With pre-designed templates, the process of creating web pages becomes much faster. Instead of starting from scratch, you can simply select a template that fits your needs and modify it to suit your content.

2. Flexibility and Customization:

  • The ability to customize section properties—from text and images to layouts and headings—ensures that your page aligns with your organization’s branding while allowing for personal adjustments.

3. Real-Time Preview:

  • The Preview feature allows you to instantly see how your page will look across devices. This ensures that your page is mobile-responsive, aesthetically pleasing, and ready for prime-time publishing.

4. Empowering Non-Developers:

  • Thanks to SharePoint’s drag-and-drop interface, even users with little to no development experience can quickly create professional pages. The ease of use is one of the platform's strongest features, making it accessible for everyone in your organization to contribute to content creation.


Advantages of Section Templates:

  • Consistency: Ensures uniform layout structure within a single page for a professional look.
  • Time-saving: Pre-designed sections make it quick and easy to build structured content without starting from scratch.
  • Flexibility: Offers customization options for text, images, and content layout within the selected section.
  • Mobile Responsiveness: Automatically adjusts to provide an optimal viewing experience across devices. 
  • User-friendly: No coding required, making it easy for non-developers to create visually appealing pages. 


Disadvantages to Consider:

  • Limited Scope: Section templates apply only to a single page, with no cross-page functionality for consistency across multiple pages. 
  • Customization Constraints: While flexible, templates may not allow advanced customizations for complex page layouts.
  • Dependency on Pre-Designed Layouts: Overreliance on templates could lead to uniformity across pages, reducing uniqueness.
  • Performance Issues: Certain complex sections might introduce performance bottlenecks if not optimized properly.

 

Conclusion:

The introduction of Modern Section Templates in SharePoint has dramatically improved the content creation process. These tools allow users to quickly build professional, brand-consistent pages without needing advanced design skills or coding experience. Whether you’re updating a page with a new event, creating a team introduction, or posting an internal status update, these features make it easier than ever to create pages that look great and are optimized for mobile devices.

With real-time previews, customizable section properties, and a growing library of templates, SharePoint’s new features bring efficiency and flexibility to web content management. While there are limitations, such as limited customization options and potential for design uniformity, the benefits - time savings, ease of use, and consistency are undeniable. These tools are a game-changer for both developers and non-developers alike.

So, whether you’re building your first page or refining an existing one, SharePoint’s Section Templates are here to help you create stunning web pages that are ready to publish at the click of a button.


If you have any questions you can reach out our SharePoint Consulting team here.

June 12, 2025

Embed PDFs in Power Apps Using the Experimental PDF Viewer

Introduction

Power Apps now offers an experimental PDF Viewer control that lets you display PDFs directly within your app interface. This is especially helpful in use cases like displaying reference documents, training guides, or reports stored in SharePoint Document Libraries - without requiring users to download them.

Below is a detailed, step-by-step guide to help you display a PDF stored in SharePoint within your Power Apps application using the experimental PDF Viewer control. 

Power Apps - PDF Viewer

Step-by-Step Instructions:

Step 1: Open or Create a Power Apps Project 

  • Navigate to https://make.powerapps.com.
  • Either:
  • Create a new Canvas app (start from blank), or
  • Open an existing app where you want to display the PDF.

Step 2: Connect to SharePoint Document Library 

  1. From the left panel, click on Data.
  2. Click on + Add data.
  3. Search for SharePoint and select it.
    Add data source in Power apps

  4. Choose your account, paste or search for your SharePoint Site URL, and then click Connect.
  5. Select your Document Library where your PDFs are stored, then click Connect.
  6. (Optional) Open your SharePoint Document Library in a new tab and upload your PDF if it's not already available. This ensures the document can be linked and previewed in Power Apps.

Step 3: Insert the Experimental PDF Viewer 

  1. In Power Apps, click on the Insert or + icon on the left toolbar.
  2. Use the search bar to search for PDF Viewer (experimental).
    Insert PDF viewer (experimental)

  3. Click to insert it into your screen.

Step 4: Set Up PDF Viewer to Display a File 

Start by using this formula in the Document property of the PDF Viewer: 

LookUp(Documents, Name = "Sample PDF.pdf").'Link to item'

Note: This may not always work as expected in Power Apps. If the PDF doesn't load, try the workaround method below to generate a direct file link. 

Workaround: Generate a Direct PDF URL Manually 

Sometimes Power Apps doesn't support rendering the default SharePoint link ('Link to item'). Instead, you can manually create a direct PDF link. 


Steps to generate a working PDF link: 

1. In SharePoint Document Library:

  1. Click on + Add Column > Select Hyperlink.
  2. Name it: Link

2. Once the column is created, go to Library Settings, then click on the Link column. 

  1. Change Format URL as: from Hyperlink to Picture.
    Library Setting - Hyperlink to Link

3. Back in your Document Library: 

  1. Click on the ellipsis (...) next to the PDF file.
  2. Click Open in browser. The PDF opens in a new tab.
  3. Copy the full URL. Remove everything after .pdf so that the link ends with .pdf.

4. Go back to your document library and:

  1. Click on Edit in grid view.
  2. Paste this cleaned-up PDF URL into the Link column for that file.
  3. Click Exit grid view to save changes. 

Edit in grid and update the url - remove extra from the link ends with .pdf
Step 5: Update Power Apps to Use the Cleaned URL 

Finally, update the Document property of the PDF Viewer to reference your new link column: 

LookUp(Documents, Name = "Sample PDF.pdf").Link

Success! Your PDF should now render properly inside the Power Apps screen. 

Show PDF in Power Apps using PDF viewer


Pro Tips:

  • Use Preview mode (F5) to test PDF rendering.
  • Ensure your PDF link ends with .pdf - any additional query parameters or tokens may break it.
  • This experimental control works best with direct-access or publicly accessible links.

Use Case Example:

This method is ideal for onboarding portals, document approval systems, training guides, or resource libraries where documents need to be viewed quickly without download. 


Conclusion:

Embedding PDFs within Power Apps is now easier thanks to the experimental PDF Viewer control. With a direct SharePoint link configured properly, you can enable seamless in-app PDF viewing for onboarding guides, reference documents, and more - without needing third-party tools or downloads. 

If you have any questions you can reach out our SharePoint Consulting team here.