The previous posts in this series covered why Microsoft built @microsoft/spfx-cli and how to use it for basic project scaffolding. This post goes deeper — into the capabilities that matter most for enterprise teams, platform engineers, and DevOps workflows.
@microsoft/spfx-cli is not just a replacement for yo @microsoft/sharepoint. It is a platform for standardized, automated SPFx scaffolding at scale. This post covers custom org templates, CI/CD integration, air-gapped environments, scaffold logging, and the programmatic API.
As of May 2026, all features covered here are available in the current pre-release (0.1.0-pre.3).
System Requirements
To use @microsoft/spfx-cli, ensure you have:
- Node.js
>=22.14.0 <23.0.0or>=24.12.0 <25.0.0 - npm, pnpm, or yarn (optional — the CLI can skip dependency installation)
Verify your Node version:
node --version
Custom Org Templates
The most strategically important feature of @microsoft/spfx-cli for enterprise teams is the ability to use custom, organization-specific templates.
Why This Matters
When teams scaffold from the standard Microsoft templates, they get a clean starting point. But enterprise SPFx solutions typically have patterns and conventions that differ from the defaults: custom base classes, shared service abstractions, specific ESLint configurations, internal CI configurations, approved third-party libraries.
Until now, teams enforced these patterns either by post-scaffolding scripts, custom Yeoman generators (which are complex to build and maintain), or documentation telling developers what to manually change after scaffolding. None of these are clean solutions.
@microsoft/spfx-cli supports pointing the CLI at a custom GitHub-hosted template repository, making organization-standard scaffolding a first-class operation.
Setting Up a Remote Template Source
To use a custom template repository, use the --remote-source flag:
spfx create \ --template acme-standard-webpart \ --library-name portal-webpart \ --component-name "Employee Directory" \ --remote-source https://github.com/acme-corp/spfx-templates
The template repository must follow the same structure as the official SharePoint/spfx templates. The CLI expects the same ZIP structure when fetching templates.
You can also set the repository URL via an environment variable to avoid repeating it in every command:
export SPFX_TEMPLATE_REPO_URL=https://github.com/acme-corp/spfx-templatesspfx create --template acme-standard-webpart --library-name my-lib --component-name "My WP"
Pinning to a Specific Template URL
For precise control — such as pinning to a specific commit or release tag — use --template-url to provide the full ZIP URL directly:
spfx create \ --template webpart-react \ --library-name my-lib \ --component-name "My WP" \ --template-url https://codeload.github.com/acme-corp/spfx-templates/zip/refs/tags/v1.2.0
GitHub Enterprise Support
Enterprise environments that use GitHub Enterprise Server rather than GitHub.com need authenticated access to fetch template archives. @microsoft/spfx-cli supports this via the GITHUB_TOKEN environment variable:
export GITHUB_TOKEN=ghp_your_token_herespfx create \ --template acme-standard-webpart \ --library-name enterprise-lib \ --component-name "Portal Header" \ --remote-source https://github.enterprise.acme.com/acme-corp/spfx-templates
Set GITHUB_TOKEN to a Personal Access Token (PAT) with repo scope on the template repository. In CI environments, store this as a secret and inject it into the pipeline environment.
Air-Gapped Environments
Some enterprise environments have no outbound internet access. @microsoft/spfx-cli supports fully offline scaffolding using a locally available template source via --local-source:
spfx create \ --template webpart-react \ --library-name offline-lib \ --component-name "Offline WP" \ --local-source /path/to/local/spfx-templates
The --local-source flag tells the CLI to read templates from a local directory instead of fetching from GitHub. You can pre-populate this directory by:
- Cloning the template repository on a machine with internet access
- Transferring the clone to the air-gapped environment
- Pointing
--local-sourceat the cloned directory
This pattern is particularly useful in regulated environments where all external network access requires approval and pre-vetting.
CI/CD Integration
The SPFX_CI_MODE Flag
In a CI/CD environment, deterministic output is important. By default, @microsoft/spfx-cli generates random UUIDs for component IDs. This is correct behavior for local development — each scaffold should produce unique component identifiers. But in automated pipelines, random UUIDs can cause unnecessary diff noise or complicate reproducible build verification.
Setting SPFX_CI_MODE=1 enables deterministic UUID generation — the same inputs produce the same UUIDs on every run:
SPFX_CI_MODE=1 spfx create \ --template webpart-react \ --library-name pipeline-lib \ --component-name "Automated Component" \ --package-manager none
Use --package-manager none in CI pipelines to separate the scaffold step from the dependency installation step. This allows you to control when npm install runs and keeps the pipeline stages composable.
GitHub Actions Example
Here is a complete GitHub Actions workflow for scaffolding a new SPFx React web part as part of an automated project setup:
name: Scaffold SPFx Projecton: workflow_dispatch: inputs: library_name: description: 'npm library name (e.g. my-spfx-lib)' required: true component_name: description: 'Component display name (e.g. Hello World)' required: true template: description: 'Template name' required: true default: 'webpart-react' type: choice options: - webpart-react - webpart-minimal - extension-listviewcommandset - extension-application-customizer - ace-generic-primarytext-cardjobs: scaffold: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' - name: Install spfx-cli run: npm install -g @microsoft/spfx-cli - name: Scaffold SPFx project run: | SPFX_CI_MODE=1 spfx create \ --template ${{ github.event.inputs.template }} \ --library-name ${{ github.event.inputs.library_name }} \ --component-name "${{ github.event.inputs.component_name }}" \ --target-dir ./projects/${{ github.event.inputs.library_name }} \ --package-manager none - name: Install dependencies working-directory: ./projects/${{ github.event.inputs.library_name }} run: npm install - name: Build to verify scaffold working-directory: ./projects/${{ github.event.inputs.library_name }} run: npm run build - name: Upload scaffolded project uses: actions/upload-artifact@v4 with: name: scaffolded-${{ github.event.inputs.library_name }} path: ./projects/${{ github.event.inputs.library_name }}
This workflow:
- Accepts inputs for library name, component name, and template choice
- Installs
@microsoft/spfx-cli - Scaffolds the project with
SPFX_CI_MODE=1 - Installs dependencies
- Runs a build to verify the scaffold produced a working project
- Uploads the scaffolded project as a pipeline artifact
Using Custom Org Templates in CI
When using org-specific templates in a pipeline, inject both the template repo URL and GitHub token as secrets:
- name: Scaffold with org templates env: GITHUB_TOKEN: ${{ secrets.SPFx_TEMPLATES_TOKEN }} SPFX_TEMPLATE_REPO_URL: ${{ vars.SPFX_TEMPLATE_REPO_URL }} run: | SPFX_CI_MODE=1 spfx create \ --template acme-standard-webpart \ --library-name ${{ inputs.library_name }} \ --component-name "${{ inputs.component_name }}" \ --package-manager none
Store SPFX_TEMPLATE_REPO_URL as a repository variable and SPFx_TEMPLATES_TOKEN as an encrypted secret. This keeps the pipeline clean and avoids hardcoding organizational infrastructure URLs in workflow files.
The Scaffold Log
Every spfx create invocation appends a structured entry to .spfx-scaffold.jsonl in the project directory. This is a JSONL (newline-delimited JSON) file — one JSON object per line, one entry per scaffold run.
Example entry (illustrative):
{"timestamp":"2026-05-01T10:23:45.000Z","template":"webpart-react","libraryName":"my-spfx-lib","componentName":"Hello World","spfxVersion":"latest","packageManager":"npm","ciMode":false}
The scaffold log is useful for:
- Audit trails: Track when a project was scaffolded, with which template and parameters
- Debugging: Understand exactly what parameters were used if a scaffold produces unexpected output
- Team tooling: Parse the JSONL file in internal tooling to track scaffolding activity across a team
In repositories where multiple developers scaffold components over time, the log provides a machine-readable record of every scaffold operation.
@microsoft/spfx-template-api: The Programmatic API
For teams building internal CLIs, editor extensions, or other custom tooling on top of SPFx scaffolding, @microsoft/spfx-template-api exposes the rendering engine as a Node.js SDK.
Installing the SDK
npm install @microsoft/spfx-template-api
Key Capabilities
The SDK provides the same template rendering engine that spfx create uses internally, exposable in your own tooling. One notable utility is the ICasedString type, which automatically converts a name string into all common casing variants:
import { ICasedString } from '@microsoft/spfx-template-api';const name: ICasedString = createCasedString('Employee Directory');// name.camelCase → 'employeeDirectory'// name.pascalCase → 'EmployeeDirectory'// name.hyphenCase → 'employee-directory'// name.upperSnakeCase → 'EMPLOYEE_DIRECTORY'
Templates use these casing variants to generate correctly-named TypeScript classes, manifest IDs, and package names from a single human-readable input.
Use Cases
- Internal scaffolding CLIs: Build a company-specific
acme-create-spfxtool that wraps the template API with org-specific defaults and validation - Editor extensions: Generate SPFx components from a VS Code extension or similar without spawning a subprocess
- Pipeline tooling: Programmatically scaffold and immediately post-process the output before committing to a repository
- Template authoring tools: Build tooling that validates or previews a template’s output before publishing to the org template repository
Summary
The enterprise-oriented features of @microsoft/spfx-cli represent a significant step forward from what was possible with yo @microsoft/sharepoint:
| Feature | Available |
Custom org templates (--remote-source) | Yes |
GitHub Enterprise support (GITHUB_TOKEN) | Yes |
Air-gapped scaffolding (--local-source) | Yes |
Deterministic CI builds (SPFX_CI_MODE=1) | Yes |
| GitHub Actions integration | Yes (flags-based, easily scriptable) |
Scaffold audit log (.spfx-scaffold.jsonl) | Yes |
Programmatic API (@microsoft/spfx-template-api) | Yes |
Teams that manage SPFx scaffolding at scale — across multiple projects, developers, and environments — now have a tool that fits those workflows natively.
Resources
- GitHub: https://github.com/SharePoint/spfx
- Short URL: https://aka.ms/spfx/cli
- npm (
@microsoft/spfx-cli): https://www.npmjs.com/package/@microsoft/spfx-cli - npm (
@microsoft/spfx-template-api): https://www.npmjs.com/package/@microsoft/spfx-template-api - Docs: https://learn.microsoft.com/en-us/sharepoint/dev/spfx/toolchain/sharepoint-framework-cli
- Architecture doc: https://github.com/SharePoint/spfx/blob/main/common/docs/spfx-cli-architecture.md