Install
$ agentstack add skill-pnp-ai-skills-spfx-best-practices ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
When to Use
Use this skill when:
- Creating or scaffolding new SPFx web parts, extensions (Application Customizers, Field Customizers, Command Sets) or libraries
- Reviewing or refactoring existing SPFx projects
- Extending existing solutions with new web parts or extensions while maintaining consistent patterns
- Answering questions about SPFx architecture, React, TypeScript, localization, styling (Sass), data access, authentication, Microsoft Graph, SharePoint APIs or tooling
Scope
Applies to:
- SPFx web parts, extensions and libraries
- React with TypeScript
- Localization (
locresources) - Styling with Sass modules
- Data access (SharePoint REST, Microsoft Graph, Entra ID–secured APIs)
- SPFx toolchain (Heft / gulp / webpack)
- Modern SPFx development workflows
Technology Stack Constraints
When generating code, adhere to these specific library versions and standards unless instructed otherwise:
- Framework: SharePoint Framework (SPFx)
- UI Library: Fluent UI React (
@fluentui/react) - Data Access: PnPjs v4 (
@pnp/sp,@pnp/graph,@pnp/logging) - Language: TypeScript
- State Management: React Hooks
- Styling: CSS Modules (
.module.scss) or Fluent UI Styling (mergeStyles)
Best Practices to Enforce
Project Structure & Architecture
- Use a feature-based or layered folder structure:
src/
common/
controls/
helpers/
hooks/
models/
services/
webparts/
extensions/
- Apply Separation of Concerns
- Keep UI, business logic and data access isolated
- Prefer reusable services over inline API logic
Toolchain & Build
- Target the latest supported SPFx version (e.g. 1.22.x+) if available.
- Use Heft as the primary build orchestrator instead of gulp when starting new projects
- Avoid custom gulp hacks unless absolutely required
- Do not override toolchain defaults unless there is a documented, reproducible need
- Avoid unsupported patches and nonstandard build steps
- Keep configuration minimal and aligned with SPFx defaults
- Validate guidance against current SPFx release notes before shipping
TypeScript & Code Quality
- Enable strict TypeScript settings
- Avoid
any; use interfaces, enums and generics - Prefer
async/await - Keep utilities framework-agnostic where possible
React Best Practices
- Prefer functional components and React Hooks
- Keep components small and focused
- Extract logic into custom hooks or services
- Memoize expensive operations (
useMemo,useCallback) - Use Fluent UI for consistency and accessibility
Localization
- Use SPFx
locfiles for all user-facing strings - Never hardcode display text
- Reference strings via
strings. - Ensure graceful fallback for missing translations
- Avoid string concatenation; use placeholders for plurals, dates and numbers
Styling (Sass)
- Use
.module.scssfiles scoped to components - Centralize shared variables, mixins and themes
- Avoid global CSS unless explicitly required
- Follow consistent naming conventions
- Controls: Use standard Fluent UI controls to match the M365 look and feel.
- Theming: strictly use
ThemeProvideror thethemeVariantobject passed from the base context. - Rule: Never hardcode hex colors (e.g.,
#0078d4). UsesemanticColors(e.g.,theme.semanticColors.bodyText). - Tokens: Prefer Fluent UI theme tokens over custom Sass variables for color and typography
Data Access Patterns
- Centralize data access in service classes
- Use PnPjs for most SharePoint operations if available
- Use SPHttpClient when:
- Performing simple or low-level REST calls
- Avoiding additional abstractions
- Handle errors, throttling and retries explicitly
- Prefer @pnp/sp and @pnp/graph for SharePoint and Graph REST interactions. Use native clients only when PnPjs is not available or when minimizing bundle size is a strictly stated priority.
Decision Matrix: PnPjs vs Native Clients
- Use @pnp/sp for SharePoint data access whenever possible
- Use @pnp/graph for Microsoft Graph when PnPjs is available
- Use MSGraphClientV3 only when PnPjs is not available or cannot be added
- Use SPHttpClient for minimal, low-level REST calls or bundle size constraints
Authentication & API Usage
- Use SPHttpClient or PnPjs for SharePoint REST APIs
- Use MSGraphClientV3 for Microsoft Graph access when PnPjs is not available
- Use AadTokenProvider for Entra ID–secured custom APIs
- Request least-privilege permissions
- Ensure Graph scopes align with
webApiPermissionRequestsand require admin consent - Never store secrets in client-side code
Performance
- Lazy-load heavy components and libraries
- Use dynamic imports when appropriate
- Minimize bundle size
- Avoid unnecessary re-renders and excessive state
- Virtualize large lists and tables
- Avoid state updates in render loops
Security
- Sanitize and validate all user input
- Respect tenant and site permissions
- Validate API responses before usage
- No Secrets: Never put client secrets or API keys in client-side code.
- Least Privilege: Suggest the minimum required
webApiPermissionRequestsinpackage-solution.json. - DOM Access: Never use
document.getElementById. Use ReactuseRef. - Avoid
dangerouslySetInnerHTMLunless the content is sanitized
Testing & Quality
- Write unit tests for services and core logic
- Use Jest + React Testing Library for components and hooks
- Enforce ESLint and Prettier
- Keep dependencies updated
- Remove dead or commented-out code, unused imports and console logs before shipping
Accessibility
- Ensure keyboard navigation and visible focus states
- Provide labels and aria attributes for all interactive controls
- Validate color contrast when using theme tokens
Anti-Patterns to Avoid
- Hardcoded strings, colors, or dates
- Data access embedded in React components
- Direct DOM access instead of
useRef - Skipping error states or swallowing exceptions
- Rendering large lists without virtualization
- Accessibility regressions (missing labels, focus traps, low contrast)
Do / Don't (Quick Scan)
| Do | Don't | | --- | --- | | Use strings. and placeholders | Hardcode user-facing strings | | Use themeVariant and Fluent UI tokens | Hardcode hex colors | | Centralize APIs in services | Call REST/Graph from components | | Use @pnp/graph when available | Default to MSGraphClientV3 | | Add keyboard support and labels | Ship UI without a11y checks |
Telemetry & Logging
- Use
@pnp/loggingor SPFxLogfor error and diagnostic logging - Never log secrets or PII
Checklist
Before generating SPFx code, follow these steps:
- Context Check: Is this a Web Part, an Extension (Application Customizer, ListView), or a Library Component?
- Environment Check: Check
Environment.type(Local, SharePoint, Classic) to avoid errors during local workbench testing. - Dependency Check: Ensure
@pnp/spand@pnp/graphimports match v4+ syntax (imports from@pnp/sp/presets/allare deprecated; use selective imports like@pnp/sp/webs). - Error Handling: Wrap all async calls in
try/catchblocks and define a UI state for errors.
Code Template: Functional Web Part
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import { MyComponent } from './components/MyComponent';
import { IMyComponentProps } from './components/IMyComponentProps';
export interface IMyWebPartProps {
description: string;
}
export default class MyWebPart extends BaseClientSideWebPart {
private _sp: ReturnType;
protected async onInit(): Promise {
await super.onInit();
// Initialize PnPjs
this._sp = spfi().using(SPFx(this.context));
}
public render(): void {
const element: React.ReactElement = React.createElement(
MyComponent,
{
description: this.properties.description,
context: this.context,
sp: this._sp
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
}
Expected Outcomes
When this skill is applied, agent should:
- Generate idiomatic SPFx + React + TypeScript code
- Highlight and explain SPFx anti-patterns
- Enforce modular, service-based architecture
- Apply localization, Sass modules and API best practices
- Prefer modern tooling (Heft) and current guidance
Tone
- Clear, pragmatic and professional
- Explain why recommendations matter
Example Prompt
- Review this SPFx solution and refactor it using SPFx best practices, including localization, Sass modules, Graph & SharePoint access and Heft-based tooling.
Additional Prompt Examples
- Scaffold a new SPFx React web part using PnPjs v4, strict TypeScript, localization with
locand.module.scssstyling.
- Refactor this web part to move all REST calls into services, add proper error handling and remove any hardcoded strings.
- Build an Application Customizer that injects a command bar using Fluent UI, with theme-aware styling and no hardcoded colors.
- Decide whether to use
@pnp/graphorMSGraphClientV3for this Graph call and explain why.
- Audit this solution for performance and accessibility issues, then provide prioritized fixes.
- Update this project to a Heft-based build and remove any nonstandard gulp customizations.
- Add a new web part to this existing SPFx solution, matching its architecture, localization and theming patterns.
- Add a Field Customizer to this solution using Fluent UI and theme tokens, with no direct DOM access.
- Migrate this legacy SPFx web part to a service-based architecture with PnPjs v4 and strict TypeScript.
Non-Goals
- Classic (non-SPFx) SharePoint customizations
- Backend-only implementations
- Over-optimization at the expense of readability
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: pnp
- Source: pnp/ai-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.