Skip to content

SharePoint

SharePoint Framework (SPFx) Complete Guide

Learn SPFx development end to end: project setup, React web parts, PnPjs, Microsoft Graph, REST, extensions, security, App Catalog deployment, and troubleshooting.

Suresh Girinathuni
Published
Reading time
25 min read
SPFx complete guide illustration showing the development lifecycle from scaffolding and local testing to deployment and operations

What you’ll learn

  • When should you use SPFx
  • SPFx architecture
  • SPFx development lifecycle
  • Development environment
  • Version compatibility

Direct answer: SharePoint Framework (SPFx) is Microsoft's extensibility model for building client-side solutions that integrate with SharePoint and Microsoft 365. SPFx builds web parts, extensions, custom list and library experiences, Microsoft Graph integrations, SharePoint API integrations, external API integrations, and Teams-integrated experiences where supported — in TypeScript and React, secured by Microsoft Entra ID, and shipped as versioned packages.

  1. SharePoint and Microsoft 365 — the host: pages, lists, Teams, and workloads.
  2. SPFx — web parts, extensions, React, PnPjs, SharePoint APIs, Microsoft Graph, external APIs.

This guide teaches the complete lifecycle — understand, set up, build, connect, secure, test, package, deploy, operate, troubleshoot — with current toolchain guidance. For navigation across the topic, use the SPFx hub; for legacy modernization decisions, use Script Editor to SPFx modernization.

When should you use SPFx

Custom development creates maintenance, testing, security, and deployment responsibilities that outlive the build. Route every requirement downward before committing to code:

  1. Requirement — confirmed with an owner.
  2. Native Microsoft 365 capability? — yes goes native.
  3. JSON formatting enough? — presentation-only needs stop here.
  4. Workflow or automation? — yes evaluates Power Automate.
  5. Business application? — yes evaluates Power Apps where appropriate.
  6. Custom SharePoint or Microsoft 365 UI? — yes evaluates SPFx.

SPFx is powerful but justified only where custom development earns its lifetime cost. Compare against Power Apps vs SPFx for the closest boundary.

SPFx architecture

  1. User — authenticated by Microsoft Entra ID with single sign-on.
  2. SharePoint Online — pages, lists, and surfaces hosting the solution.
  3. SPFx component — web part or extension running in user context.
  4. React and TypeScript — UI layer and type-safe logic.
  5. Service layer — PnPjs, SharePoint REST, Microsoft Graph, external APIs.
  6. Microsoft 365 and business systems — data behind the experience.

Identity flows through every layer: Entra ID authenticates the user, SharePoint user permissions bound SharePoint access, and approved API permission grants bound Graph and API access. Later sections verify each layer independently.

SPFx development lifecycle

  1. Plan — requirement, data, permissions, environments.
  2. Scaffold — generate the project with current tooling.
  3. Develop — components, services, and configuration.
  4. Test — local, personas, error paths.
  5. Build — compile, bundle, optimize.
  6. Package — versioned solution package.
  7. Deploy — App Catalog to sites.
  8. Approve permissions — administrator review of API scopes.
  9. Validate — production behavior and access.
  10. Monitor — errors, usage, dependencies.
  11. Maintain — versions, upgrades, ownership.

Development does not end when code compiles — packaging, approval, validation, and operations are part of the lifecycle, and this guide treats them as first-class stages.

Development environment

Set up against current Microsoft guidance for the SPFx release being targeted — verified against the official setup documentation at the time of writing, and re-check before starting because these requirements move. The current baseline for recent SPFx releases:

  • Node.js — a supported LTS release matching your SPFx version (recent releases target Node.js v22 LTS). Confirm with node --version; SPFx is only supported on LTS releases.
  • Package manager — npm, confirmed with npm --version.
  • Generator and toolchain — Yeoman plus the SharePoint generator plus the build orchestrator for your SPFx release, installed globally (see the version section below for which orchestrator applies).
  • Editor and browser — Visual Studio Code or any client-side-capable editor, plus a modern browser for testing.
  • Microsoft 365 developer tenant — required before testing against real SharePoint data; never develop directly against production.
  • Operating system — macOS, Windows, or Linux are all supported.

Official reference: Set up your SharePoint Framework development environment on Microsoft Learn.

Version compatibility

SPFx version compatibility matters because the framework, Node.js, TypeScript, React, and the build toolchain move together — mismatched combinations produce failures that look like broken code. The critical fact, verified against current Microsoft documentation:

SPFx release lineBuild toolchainWhat changes
v1.0 through v1.21.xLegacy gulp-based toolchaingulp tasks, gulpfile customization, legacy setup guide applies
v1.22 and laterHeft-based toolchain (default for new projects)Heft orchestration, config-driven rig, webpack still bundles underneath

Older and newer SPFx versions genuinely use different toolchains: commands such as the legacy gulp serve, bundle, and package-solution tasks belong to pre-v1.22 projects and must not be copied into current-version tutorials. If you maintain an older project, follow the legacy gulp-toolchain setup guide for that release line; for new work, follow the Heft-based guidance below. Always confirm the Node.js LTS, TypeScript, and React versions supported by your exact SPFx release before installing anything.

Official references: Heft-based toolchain and the SPFx roadmap update for platform direction.

Create an SPFx project

Create a project directory, then scaffold with the current SharePoint generator — verified against the official Hello World tutorial:

mkdir spfx-documents-webpart
cd spfx-documents-webpart
yo @microsoft/sharepoint

Answer the generator prompts for your goal — for a first web part: component type WebPart, your web part name, and your framework choice (React for the patterns in this guide). The generator creates the scaffolding and installs dependencies, then reports the command to start developing (see the testing section). Key inputs to get right at scaffolding time are the solution name, component type, web part name, and framework selection, because they shape the generated project described next.

Official reference: Build your first SharePoint client-side web part on Microsoft Learn.

Project structure

Know what each generated area does, when developers normally change it, and what to leave alone:

PathWhat it doesChange guidance
src/Web parts, components, services, styles, localizationDaily working area — components and services live here
config/Build, bundle, serve, and deployment configurationAdjust deliberately; understand before editing
sharepoint/Solution packaging inputsTouch for packaging metadata and assets
package.jsonDependencies and npm scripts for the toolchainAdd dependencies carefully; use provided scripts
TypeScript configCompiler behavior for the projectRarely changed outside toolchain upgrades
Component manifestWeb part metadata: ID, version, hosts, defaultsVersion and metadata intentionally per release
Localization filesUser-facing strings per languageExternalize strings here, never inline copy
Toolchain rig filesShared build configuration (current toolchain)Reference, do not fork casually

Exact filenames vary by SPFx and toolchain release — treat this table as a map of responsibilities, and confirm names against your generated project.

Web part anatomy

A web part class extends the framework base class, declares typed properties, renders a React component into its DOM element, and exposes configuration through the property pane and manifest:

  1. Web part — class, lifecycle, manifest, deployment identity.
  2. Properties — typed values authors configure.
  3. React component — rendering from props and state.
  4. Service — data access behind an interface.
  5. SharePoint, Graph, or API — data behind the service.

The base class supplies lifecycle, context, display mode, instance identity, and the DOM element. Your code supplies properties, rendering, and services — nothing else belongs in the web part class.

React in SPFx

Use modern React patterns supported by your SPFx release: functional components, props, state, hooks including useEffect, event handling, loading and error states, and component composition. Never fetch data inside render paths — effects and services own that work:

import * as React from "react";

export interface IDocumentsProps {
  title: string;
  items: string[];
  loading: boolean;
  error?: string;
}

export function Documents(props: IDocumentsProps): JSX.Element {
  if (props.loading) {
    return <p>Loading documents…</p>;
  }
  if (props.error) {
    return <p>Documents are unavailable right now. Try again later.</p>;
  }
  if (props.items.length === 0) {
    return <p>No documents found.</p>;
  }
  return (
    <section>
      <h2>{props.title}</h2>
      <ul>
        {props.items.map((name) => (
          <li key={name}>{name}</li>
        ))}
      </ul>
    </section>
  );
}

Props carry data down, state tracks loading and failure, and every branch — loading, error, empty, data — renders deliberately. Match the React version supported by your SPFx release; this guide teaches patterns, not React itself.

TypeScript in SPFx

TypeScript is the primary SPFx language: interfaces and types describe web part properties, service contracts, and API shapes; async and await structure data calls; generics type reusable services where useful; explicit null handling removes whole classes of runtime surprises:

export interface IDocument {
  id: number;
  title: string;
  url: string;
}

Model every service boundary with interfaces like this one — components receive typed data, never raw API payloads.

Fluent UI

Fluent UI supplies Microsoft 365-aligned buttons, inputs, dialogs, panels, and details experiences with an accessibility baseline generic controls lack. Confirm which Fluent UI approach fits the current SPFx ecosystem before adding anything — versions and packages move with SPFx releases, so verify against current guidance rather than copying install commands from older samples. Never stack a second UI framework on top without a reason the design can defend.

Property pane

Configurable properties — title, list, display mode, item counts, feature flags — flow from editor to property pane to web part properties to React component. Define them with the framework's property pane fields, type them in the props interface, and default them in the manifest's properties bag:

import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField,
  PropertyPaneToggle
} from "@microsoft/sp-property-pane";

export interface IHelloWorldWebPartProps {
  description: string;
  showWelcome: boolean;
}

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
  return {
    pages: [
      {
        header: { description: "Display settings" },
        groups: [
          {
            groupFields: [
              PropertyPaneTextField("description", {
                label: "Description"
              }),
              PropertyPaneToggle("showWelcome", {
                label: "Show welcome",
                onText: "On",
                offText: "Off"
              })
            ]
          }
        ]
      }
    ]
  };
}

Property panes are reactive by default — authors see changes as they edit — and every value read in rendering is escaped or validated before display. Confirm field availability against your SPFx release; the shape above follows the long-standing configuration pattern.

SharePoint context

The web part context exposes the current site, web, user, page context, and HTTP and Graph clients. Pass what components need through props and services — never stash context in globals, which couples every component to ambient state and breaks testability. Services receive the pieces they need (a client, a site URL) at construction; components never touch context directly.

Data access architecture

Never scatter direct API calls through UI components. Route every call through a service interface with an implementation per data source:

  1. React component — renders props and state only.
  2. Service interface — typed operations the UI depends on.
  3. Service implementation — PnPjs, REST, Graph, or API calls.
  4. PnPjs, REST, Graph, or API — the data behind the contract.

This buys testability (mock the interface), maintainability (one place per data concern), reuse across components, centralized error handling, and separation of concerns that survives team changes.

SharePoint REST

REST remains appropriate for SharePoint-specific operations — lists, items, libraries, files — especially where precise control matters. Call it through the framework HTTP client with the standard configuration, select only needed fields, and handle failures through the service layer:

import {
  SPHttpClient,
  SPHttpClientResponse
} from "@microsoft/sp-http";

export async function getListTitle(
  client: SPHttpClient,
  siteUrl: string,
  listTitle: string
): Promise<string> {
  const url =
    siteUrl +
    "/_api/web/lists/getbytitle('" +
    encodeURIComponent(listTitle) +
    "')?$select=Title";
  const response: SPHttpClientResponse = await client.get(
    url,
    SPHttpClient.configurations.v1
  );
  if (!response.ok) {
    throw new Error("List request failed with status " + response.status);
  }
  const data = await response.json();
  return data.Title as string;
}

Graph does not automatically replace every SharePoint REST endpoint — list schemas, versioning detail, and fine-grained permission structures frequently still belong on SharePoint-side APIs.

PnPjs

PnPjs wraps supported SharePoint and Graph operations — lists, items, libraries, files, users, groups, search, batching — in a fluent, typed API that removes most REST boilerplate. Initialize it with the web part context so calls run as the current user, and align the PnPjs major version with the targeted SPFx release:

import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import type { WebPartContext } from "@microsoft/sp-webpart-base";

export interface IListItem {
  id: number;
  title: string;
}

export async function getItems(
  context: WebPartContext,
  listTitle: string
): Promise<IListItem[]> {
  const sp = spfi().using(SPFx(context));
  try {
    const items = await sp.web.lists
      .getByTitle(listTitle)
      .items.select("Id", "Title")();
    return items.map((item) => ({ id: item.Id, title: item.Title }));
  } catch (error) {
    throw new Error(
      "Could not read list. Confirm it exists and the user can access it."
    );
  }
}

Request only necessary fields, batch independent reads, and keep every call behind the service interface. Verify current package names against official PnP documentation before implementing.

Microsoft Graph

Graph fits users, groups, Teams, OneDrive files, and Microsoft 365 services reached from SPFx through the Graph client — under delegated permissions a tenant administrator approves, following least privilege, with 401 and 403 handled distinctly:

import type { WebPartContext } from "@microsoft/sp-webpart-base";
import type { MSGraphClientV3 } from "@microsoft/sp-http";

export async function getMyDisplayName(
  context: WebPartContext
): Promise<string> {
  const client: MSGraphClientV3 =
    await context.msGraphClientFactory.getClient("3");
  try {
    const me = await client.api("/me").select("displayName").get();
    return me.displayName as string;
  } catch (error) {
    throw new Error(
      "Could not read the current user. Confirm Graph permission approval."
    );
  }
}

Request least-privilege scopes, obtain admin consent where required, and never assume automatic access to all Microsoft 365 data. Verify the client pattern against current documentation for your SPFx release. Concepts: Microsoft Graph for beginners and what Microsoft Graph is.

SharePoint REST versus PnPjs versus Graph

TechnologyBest fitStrengthsConsiderations
SharePoint RESTSharePoint-specific operationsPrecise control, no abstractionVerbose; manual batching and typing
PnPjsDeveloper convenience over supported APIsFluent, typed, batteries includedVersion alignment with the SPFx release
Microsoft GraphCross-Microsoft 365 dataOne surface, delegated permissionsNot every SharePoint operation is exposed

Real solutions routinely combine two or all three — Graph for people and files, PnPjs or REST for list internals. The operation decides, never habit.

External API integration

Enterprise APIs enter through Microsoft Entra authentication against secured endpoints, with a backend mediation layer wherever the API cannot authenticate the user directly. SPFx runs in the browser, so it can never embed client secrets, passwords, privileged API keys, or long-lived sensitive credentials — bundles are downloadable by design. The documented client for Entra-secured APIs applies here; verify its current guidance for your SPFx release before implementing, and move any secret-bearing call behind the mediated backend.

  1. SPFx — user-context request.
  2. Microsoft Entra ID — identity without embedded secrets.
  3. Protected API — authorized endpoint.
  4. Business system — data under proper authorization.

CORS

Browser origin rules cause CORS failures when the API has not allowed the SharePoint origin: preflight rejections and blocked responses are server-configuration facts, not SPFx bugs. Never suggest disabling security controls as a workaround — fix allowed origins on the API side or route through a secure backend. When direct browser calls cannot be authorized cleanly, mediation is the architecture, not a fallback.

Authentication versus authorization

Authentication answers who the user or application is; authorization answers what it may do. The chain runs user, SPFx, token, API, authorization — and Microsoft Entra ID underpins identity while each API enforces its own access rules. Debugging starts by naming which link failed: sign-in and consent problems are authentication; denials for a signed-in user are authorization.

  1. User — authenticated with single sign-on.
  2. SPFx — acquires tokens for declared resources.
  3. Token — scoped identity proof, never a secret to log.
  4. API — validates token and scope.
  5. Authorization — grants or denies the operation.

API permissions

Protected calls need approved permission grants: declare least-privilege scopes in the solution, submit them for tenant administrator review, and treat approval as a deployment gate — unapproved permissions fail at runtime, not at build time. Verify the current approval workflow before documenting UI steps, since admin center experiences evolve; the invariant is request, review, approve, then runtime access.

  1. SPFx solution — declares required scopes.
  2. Permission request — visible to reviewers.
  3. Tenant admin review — least privilege scrutinized.
  4. Approved permission — recorded per solution version.
  5. Runtime access — succeeds under the grant.

SharePoint user permissions versus API permissions

SharePoint permissions control the user's SharePoint access; API permissions control application and API access — and a Graph grant never gives the current user unrestricted access to everything. Behavior follows the API pattern in use: delegated user-context calls stay bounded by what the user may touch, which is why effective-access testing with real personas remains mandatory. Confusing the two layers is the most common authorization misunderstanding in SPFx work.

SPFx extensions

Extensions customize the experience around content: Application Customizers for page-level scenarios, ListView Command Sets for row commands, and Field Customizers for column rendering. Each deploys as a package through the App Catalog with the same permission model as web parts. Keep this section as orientation — one practical scenario per type below, with dedicated deep-dives tracked as future content.

Application Customizer

Appropriate for supported application-level UI scenarios such as headers, footers, banners, and page behavior through supported placeholders. Never present it as a replacement for arbitrary master-page manipulation — classic chrome hacks do not transfer, and the requirement gets redesigned instead.

  1. Modern SharePoint — page with supported placeholders.
  2. SPFx Application Customizer — scoped,reviewed chrome.
  3. Supported extension experience — survives service updates.

ListView Command Set

Custom commands for supported list and library scenarios: select a document, invoke the custom command, and run the business action or API call. Respect selection context (single versus multiple rows), verify the acting user's permissions before executing, and handle empty or mixed selections explicitly.

  1. Select document — rows provide context.
  2. Custom command — validated against selection and access.
  3. Business action or API — executed with error handling.

Field Customizer

Custom field rendering scenarios belong here when declarative JSON formatting cannot carry the requirement. Compare honestly per column: JSON where presentation suffices, SPFx where supported custom rendering or business logic justifies code. No universal winner — the column decides. Reference: what SPFx extensions are.

State management

Most web parts need only React state, hooks, and context. Avoid adding heavy state libraries for simple component trees — prop drilling two levels deep does not justify a store. Complex multi-view applications may require more architecture, decided per solution rather than by habit. Keep this section deliberately short: state shape follows the service contracts already defined.

Configuration without hard-coding

Tenant URLs, site URLs, list IDs, API endpoints, and environment values never belong inline. Prefer web part properties for author-configured values, configuration modules for solution constants, and environment-specific build and deployment configuration for per-stage differences — with secrets handled server-side, never in the bundle. Configuration is not secret storage: anything shipped in a browser bundle is visible to the user by definition.

Error handling

Apply one reusable model to every data call: request, loading, success renders; failure classifies, logs, and ends in a useful user message. Cover 401, 403, 404, throttling responses where relevant, server errors, network failure, and invalid configuration distinctly — each has a different owner and fix. Never expose sensitive server responses to end users; escape or validate everything rendered from properties and APIs.

  1. Request — through the service layer with loading state.
  2. Loading — skeleton or placeholder, never a blank hole.
  3. Success — renders typed data.
  4. Failure — classified by cause.
  5. Log — diagnostics without secrets or personal data.
  6. Useful user message — actionable next step, not internals.

Logging

Log operation, context, error category, and correlation information where available — enough to reproduce failures from reports alone. Never log access tokens, secrets, or sensitive personal and business data beyond need. No proprietary logging framework is prescribed here; consistency within the solution matters more than the library chosen.

Performance

Minimize unnecessary API calls, select only required fields, filter server-side where possible, paginate, batch, cache where appropriate, lazy-load secondary experiences, manage bundle size, review dependencies, render React efficiently, never load huge lists into browser memory, and design loading states. No fabricated benchmarks are published — measure each solution against its own baseline and fix what the measurements indict.

SharePoint large data

Never assume all list or library data can load client-side. Design filtering, index-aware queries where applicable, pagination, search-backed retrieval where appropriate, server-side APIs, and data virtualization where appropriate into the architecture from the start. No exact platform limits are hard-coded here — verify current values against Microsoft documentation when sizing, and design so limits constrain gracefully instead of failing loudly.

Security checklist

Accessibility

Semantic HTML, keyboard navigation, focus management, accessible labels, ARIA where appropriate, screen-reader behavior, contrast, and accessible components are implementation quality — not a final optional step. Prefer Fluent UI or native controls with built-in accessibility behavior over custom widgets that reimplement it badly.

Local development and testing

Run and preview with the current supported workflow: start the local development server from the project (which serves the local bundles and opens the hosted workbench), trusting the developer certificate once per workstation as current setup guidance describes. The hosted workbench loads local code against real tenant data — which means tenant data access, permissions, and configuration affect every test, and development assumptions must be re-verified in shared environments. Never present outdated local-workbench behavior as current; confirm the workflow against the documentation linked in the environment section.

Testing strategy

Test components, service layers, APIs, permissions, personas, error paths, configuration, and production-like conditions. Where permissions matter, exercise owner, member, and visitor or restricted personas — testing only as an administrator hides the failures users will find. Error paths and misconfiguration deserve first-class tests: denied access, missing lists, and wrong environments are normal production events, not edge cases.

Build for production

Production builds compile TypeScript, bundle and optimize assets, and prepare package artifacts through the toolchain supported by the targeted SPFx release — invoked through the project's npm scripts, never through legacy gulp tasks on current-toolchain projects. Understand conceptually what the build does even when the commands are one-liners: type-checking, bundling, minification, manifest generation, and artifact staging each catch different defect classes.

Solution package

The SharePoint solution package is the versioned distribution unit: solution metadata, features where relevant, API permission requests, and version identity traveling together. Understand what the package contains conceptually — metadata, manifests, bundles, and permission declarations — without memorizing generated internals that the toolchain owns.

App Catalog

The tenant App Catalog distributes packages organization-wide; site-collection catalogs scope distribution where currently supported and appropriate. Choose per governance needs: broad reuse favors the tenant catalog, isolated or sensitive solutions favor scoping. Verify current Microsoft guidance before stating catalog capabilities, then follow the lifecycle: developer builds, package created, catalog upload, deployment, SharePoint site availability.

  1. Developer — builds and versions the package.
  2. Build — production artifacts prepared.
  3. Solution package — versioned distribution unit.
  4. App Catalog — upload to tenant or scoped catalog.
  5. Deployment — solution enabled per governance.
  6. SharePoint site — component available to authors.
  7. SPFx component — running for real users.

Deployment lifecycle

Build, package, upload, deploy, approve API permissions, add or enable the solution, then validate in the target — with exact steps varying by solution type and current Microsoft behavior. Uploading a package alone never proves successful deployment; validation in the target with real personas closes the loop.

Solution versioning

Production solutions need version discipline: package versions that map to source control, release notes describing behavior change, deployment history per environment, rollback planning before rollout, and environment promotion in order. No mandatory semantic-versioning policy is invented here — but unversioned or unreleasable solutions are not production-grade regardless of convention chosen.

Dev, test, and production

Promote through source control into dev, test, then production, with URLs, list IDs, API endpoints, permissions, app registrations, and configuration differing per stage. Nothing environment-specific is embedded in code — configuration resolves per environment, and each stage validates the resolution before promotion.

  1. Source control — single truth for code and config templates.
  2. Dev — developer velocity with realistic data.
  3. Test — production-like permissions and configuration.
  4. Production — validated releases only.

CI and CD

Keep the pipeline conceptual and small: pull request with lint and tests, build, package, artifact, approval, deploy. GitHub Actions and Azure DevOps both express this shape; no dedicated CI article exists on nextM365 yet, so this guide stays at pipeline shape rather than a full tutorial. The invariant is gating: unreviewed code never reaches the catalog, and unvalidated packages never reach production.

  1. Pull request — review with automated checks.
  2. Lint and test — fast feedback before build.
  3. Build — production artifacts.
  4. Package — versioned distribution unit.
  5. Artifact — stored, traceable, promotable.
  6. Approval — human gate with permission review.
  7. Deploy — staged rollout with validation.

Production readiness checklist

Code: TypeScript clean; errors handled; no unnecessary dependencies; no hard-coded environment values.

Security: no secrets; least privilege; API permissions reviewed; authorization tested.

UX: loading, empty, and error states; accessibility reviewed.

Performance: API calls, data volume, bundle, and caching strategy reviewed.

Deployment: package versioned; App Catalog plan defined; permissions documented; rollback considered.

Operations: logging strategy, ownership, documentation, and support path defined.

Troubleshooting hub

SymptomCheckLikely cause categoryNext step
Project does not buildSPFx, Node, and toolchain versionsVersion mismatchAlign to the supported combination for the release
Node or toolchain compatibility errorLTS status and release support matrixUnsupported runtimeInstall the supported LTS for the SPFx release
Module not foundInstall state, package names, importsDependencies or drifted APIsReinstall, verify names against current docs
Web part not appearingDeployment scope, app installation, hostsIncomplete deployment chainComplete catalog, deploy, and add steps
Package not availableCatalog upload and deployment stateDistribution gapConfirm upload, deployment, and scope
Solution not deployedCatalog state versus site stateMissing enable stepAdd or enable the solution where designed
Graph 401Sign-in, consent, token acquisitionAuthenticationFix identity and consent before code changes
Graph 403Requested versus approved scopesAuthorizationRequest least privilege and obtain approval
API permission missingPackage declaration versus admin stateApproval gapRequest and obtain administrator approval
PnPjs request failingContext init, select clauses, batchingCall constructionReproduce as raw REST to isolate the layer
SharePoint REST 403Effective user access, request shapeAuthorization or malformed callTest as the user, then inspect the request
External API CORSAllowed origins, mediation layerServer configurationFix server-side or add mediated backend
Authenticated client 401 or 403Token resource, scopes, consentIdentity or grant gapVerify resource, scopes, and approval state
Environment URL incorrectConfiguration per environmentHard-coded or stale valuesExternalize and verify per environment
Works in dev, not productionConfig, URLs, approvals, versionsEnvironment driftDiff environments systematically
Dependency or version conflictDuplicate frameworks, lockfile driftDependency hygieneDedupe, align, and re-verify the build

Each row is triage, not a tutorial — deeper fix guides are tracked as future content. Related patterns: SPFx troubleshooting.

Common SPFx mistakes

MistakeCorrective direction
Using SPFx when native functionality sufficesRoute requirements through the decision framework first.
Copying legacy JavaScript directly into SPFxExtract requirements and redesign; evidence, not design.
Direct API calls throughout UI componentsIntroduce a service layer behind interfaces.
Hard-coded URLsExternalize to properties and environment configuration.
Secrets in browser codeMove to a secured backend; redesign the integration.
Over-requesting Graph permissionsLeast privilege, justified per scope.
Loading entire large listsFilter, paginate, and virtualize by design.
Ignoring 401, 403, and throttling handlingClassify failures with distinct handling per cause.
Ignoring accessibilityDesign keyboard, focus, and screen-reader behavior up front.
Ignoring production loggingLog operations with correlation, never secrets.
Using outdated dependenciesAlign with the targeted SPFx release and re-verify.
Ignoring Node and SPFx compatibilityMatch the supported combination before installing.
Testing only as an administratorExercise owner, member, and restricted personas.
Skipping production validationValidate in the target with real users before sign-off.

Migration and modernization bridge

SPFx is particularly relevant when migration discovers custom functionality that cannot be retained or replaced with simpler modern capabilities. Route classic findings through assessment into business requirements, then native, JSON, Power Platform, or SPFx onto modern SharePoint — with depth in Classic SharePoint to Modern SharePoint, Script Editor to SPFx modernization, and the migration hub.

  1. Classic SharePoint — custom functionality as found.
  2. Migration assessment — inventory with requirements.
  3. Legacy customization — classified per component.
  4. Business requirement — defended by an owner.
  5. Native, JSON, Power Platform, or SPFx — simplest fitting architecture.
  6. Modern SharePoint — rebuilt, secured, validated.

From Script Editor to SPFx

Modernizing legacy scripts? The companion guide routes each script through requirement analysis instead of automatic porting: Script Editor to SPFx modernization — including the decision tree this guide builds on.

Solution blueprint: enterprise SPFx application

Reference shape only — not a customer implementation. A user reaches SharePoint Online, where SPFx renders React UI backed by a service layer reaching SharePoint through PnPjs, Microsoft 365 through Graph, and business systems through a secure API — all under Microsoft Entra ID, surrounded by permissions, logging, configuration, error handling, and performance discipline.

  1. User — authenticated with single sign-on.
  2. SharePoint Online — host surfaces.
  3. SPFx — web parts and extensions.
  4. React — components from props and state.
  5. Service layer — PnPjs to SharePoint, Graph to Microsoft 365, secure API to business systems.
  6. Microsoft Entra ID — identity beneath every call.

Developer learning path

  1. SPFx fundamentals — model, lifecycle, and this guide with what SPFx is.
  2. Web parts — anatomy, properties, and rendering above.
  3. React — components, hooks, and states above.
  4. SharePoint data — REST shapes and service design above.
  5. PnPjs — service-layer patterns above.
  6. Microsoft Graph — delegated access with Graph for beginners.
  7. Extensions — surfaces and scenarios above with what extensions are.
  8. Authentication — identity and permission layers above.
  9. Deployment — packaging, catalog, and approval above.
  10. Production engineering — security, performance, logging, and operations above.

Each stage links only to genuinely existing pages — dedicated deep-dives are tracked as future content, not placeholder links.

Building a complex SPFx solution

If you are working through SharePoint modernization, Microsoft Graph, external APIs, authentication, deployment, or complex SPFx architecture, share the technical challenge with nextM365: Discuss Your SPFx Project.

Continue with Explore SPFx, planning SharePoint modernization, Script Editor to SPFx modernization, and the SPFx roadmap update.

Related resources

Share this:

Topics covered

React · Project Structure · Permissions · ALM · Security

Frequently asked questions

What is SPFx?

The SharePoint Framework is Microsoft’s client-side extensibility model for building web parts, extensions, and Microsoft 365 integrations with TypeScript and React. Solutions run in the browser in the current user’s context and deploy as versioned packages through the SharePoint App Catalog.

What can you build with SPFx?

Custom web parts, page and list extensions, field customizers, command sets, Graph-connected experiences, SharePoint data solutions, external API integrations, and Teams-integrated experiences where applicable.

When should SPFx be used?

When a confirmed requirement needs custom SharePoint or Microsoft 365 UI and no native capability, JSON formatting, Power Automate, or Power Apps approach fits. Custom development creates maintenance, testing, security, and deployment responsibilities.

Does SPFx require React?

No — web parts can use any framework or none — but React is the standard, best-supported UI layer, and current guidance and samples assume it unless a project has a specific reason to differ.

Can SPFx use PnPjs?

Yes. PnPjs simplifies supported SharePoint and Graph operations from an SPFx service layer. Align the PnPjs major version with the targeted SPFx release and verify current package names against official PnP documentation.

Can SPFx call Microsoft Graph?

Yes, through the Graph client with delegated permissions approved by a tenant administrator. Request least-privilege scopes, never assume automatic access, and handle 401 and 403 distinctly.

Can SPFx call external APIs?

Yes, through Microsoft Entra authentication against secured endpoints, adding a backend mediation layer where the API cannot authenticate the user directly. Never embed secrets in the browser bundle.

How does authentication work in SPFx?

Solutions run as the signed-in user with automatic single sign-on. Authentication identifies the user; separate authorization layers — SharePoint user permissions and approved API permission grants — decide what is allowed.

Can secrets be stored in SPFx?

No. Bundles are downloadable by design, so client secrets, passwords, and privileged keys belong in a secured backend or managed-identity flow that the solution calls.

What is an SPFx Extension?

A customization of the experience around content rather than a page component: Application Customizers for page-level scenarios, ListView Command Sets for row commands, and Field Customizers for column rendering. All deploy as packages through the App Catalog.

How is an SPFx solution deployed?

Build and bundle with the toolchain supported by the targeted SPFx release, create the versioned solution package, upload it to the tenant or site-collection App Catalog, deploy it, obtain tenant administrator approval for requested API permissions, add or enable the solution, and validate in the target.

What is the SharePoint App Catalog?

The tenant or site-collection library that distributes solution packages to SharePoint. Uploading a package makes it available; deployment, permission approval, and adding the solution to sites are separate steps.

How do you troubleshoot SPFx 403 errors?

Separate authentication (401) from authorization (403): confirm sign-in and consent, compare requested versus approved scopes, verify the user’s effective SharePoint access, and check environment configuration — fixing identity and approval first, code last.

Sources

Have a Microsoft 365 topic idea?

Share article suggestions, community session ideas, corrections, or real-world scenarios for future nextM365 learning notes.

Connect with me

Keep learning Microsoft 365

Explore more practical tutorials for SharePoint, Power Platform, Copilot Studio, migration, automation, governance, and security.

Continue learning