CodeepCodeep
← back to marketplace

sharepoint-spfx

v1.0.0

Build, debug, package and deploy SharePoint Framework (SPFx) web parts, extensions and apps for SharePoint Online and Microsoft Teams.

by VladoIvankovic · 0 installs · updated 5/18/2026

Install

/skills install VladoIvankovic/sharepoint-spfx

Runs in any Codeep session (TUI, Zed, or VS Code extension). Writes to .codeep/skills/sharepoint-spfx/SKILL.md in your project.

SKILL.md

---
name: sharepoint-spfx
description: Build, debug, package and deploy SharePoint Framework (SPFx) web parts, extensions and apps for SharePoint Online and Microsoft Teams.
version: 1.0.0
triggers:
  - sharepoint
  - spfx
  - sharepoint framework
  - sharepoint web part
  - sharepoint extension
  - teams app sharepoint
  - app catalog
  - yo @microsoft/sharepoint
  - gulp serve
  - sppkg
---
# SharePoint Framework (SPFx) — End-to-End

You are helping a developer build a SharePoint Framework solution
(SPFx) — Microsoft's modern client-side development model for SharePoint
Online, on-premises SharePoint 2019+, and Microsoft Teams. Follow this
guide whenever the user mentions SharePoint, SPFx, web parts,
extensions, or App Catalog deployment.

## Always check first

Before scaffolding or running any build, verify the environment.
**SPFx is notoriously picky about Node, npm, and gulp versions.** Mismatch
is the #1 source of "works on my machine" failures.

```bash
node --version    # SPFx 1.18+ needs Node 18.x LTS (NOT 20+)
npm --version     # 9.x or 10.x
gulp --version    # CLI: 2.3+, Local: 4.0+
yo --version      # 5.x
```

If Node is wrong, recommend `nvm install 18 && nvm use 18`. Do not
proceed until Node is on the right LTS for the target SPFx version:

| SPFx version | Node LTS | TypeScript | gulp |
| --- | --- | --- | --- |
| 1.18 (latest) | 18 | 4.7 | 4.0 |
| 1.17 | 16 or 18 | 4.5 | 4.0 |
| 1.16 | 16 | 4.5 | 4.0 |
| 1.15 | 14 or 16 | 4.5 | 4.0 |

## Scaffolding a new solution

Use the Microsoft Yeoman generator. Don't hand-roll the project — the
generator wires up gulp, tsconfig, package-solution.json, manifests
and the resource files correctly.

```bash
# One-time
npm install -g yo gulp-cli @microsoft/generator-sharepoint

# Scaffold (interactive)
mkdir my-spfx-solution && cd my-spfx-solution
yo @microsoft/sharepoint
```

The generator asks:

- **Solution name** — kebab-case
- **Target environment** — *SharePoint Online* (recommended) or *2019+ on-prem*
- **Folder** — current vs new
- **Tenant-wide deploy** — yes if you want to skip per-site enable later
- **Component type** — *Web Part* / *Extension* / *Library* / *ACE (Adaptive Card Extension)*
- **Web part name** — display name
- **Framework** — *No JavaScript framework* / *React* / *Minimal*

For most modern projects pick: **SharePoint Online → React → tenant-wide deploy: yes**.

## Project structure

```
my-spfx-solution/
├── config/
│   ├── config.json              # bundle and externals
│   ├── package-solution.json    # solution id, version, features
│   ├── serve.json               # gulp serve URL + page
│   └── write-manifests.json     # CDN url for prod bundle
├── src/webparts/<name>/
│   ├── <Name>WebPart.ts         # entry point — property pane + render()
│   ├── <Name>WebPart.manifest.json   # IDs, supported hosts, preconfigured entries
│   ├── loc/                     # localisation strings (mystrings.d.ts + en-us.js)
│   └── components/              # React components (if React framework)
├── sharepoint/                  # generated .sppkg lands here after `gulp package-solution`
├── package.json
├── tsconfig.json
└── gulpfile.js
```

Never edit anything in `lib/`, `dist/`, `temp/`, `release/`, or
`sharepoint/solution/` directly — they're build output.

## Local dev workflow

```bash
# Trust the dev cert (one-time per machine)
gulp trust-dev-cert

# Start the local workbench + watch
gulp serve

# Opens https://localhost:4321/temp/workbench.html — drop the web part on the canvas
```

For testing against a real SharePoint page (not the local workbench),
edit `config/serve.json` and set `initialPage` to a hosted workbench URL:

```json
{
  "initialPage": "https://contoso.sharepoint.com/_layouts/15/workbench.aspx"
}
```

Then `gulp serve --nobrowser` and open that URL manually with the
`?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js`
query string appended. SharePoint loads your local bundle from
`localhost:4321` instead of the CDN.

## Build and package for deployment

```bash
# Production bundle — minified, CDN-ready
gulp clean
gulp bundle --ship

# Package into .sppkg (lands in sharepoint/solution/<name>.sppkg)
gulp package-solution --ship
```

`--ship` flag is critical — without it the bundle is debug/dev quality
and the manifests point at `https://localhost:4321/`.

## Deploy to App Catalog

1. Upload `<name>.sppkg` from `sharepoint/solution/` to the
   **tenant App Catalog**:
   `https://<tenant>.sharepoint.com/sites/appcatalog/AppCatalog`
2. Click **Deploy** on the prompt. If `skipFeatureDeployment: true`
   was set in `package-solution.json`, it's tenant-wide immediately;
   otherwise you must add it per-site via Site Contents → New → App.
3. Bump version in `config/package-solution.json` (`solution.version`)
   for every update — SharePoint deduplicates by version, an upload
   with the same version silently no-ops.

## Common gotchas — surface these proactively

- **Node version drift.** If `gulp serve` errors with cryptic OpenSSL or
  `digital envelope routines::unsupported`, the user is on Node 18+
  with an SPFx version that wants Node 16. Either downgrade Node or
  set `NODE_OPTIONS=--openssl-legacy-provider` as a workaround.
- **Cert not trusted.** Browser blocks `https://localhost:4321` with a
  TLS warning even after `gulp trust-dev-cert`. On macOS: open
  Keychain Access → log-in → search "SPFx" → set to Always Trust.
- **`gulp serve` shows blank workbench.** Check the browser console — the
  manifest URL probably has a wrong port. Fix `config/serve.json` or
  re-run with `--port 4322` if 4321 is taken.
- **`gulp package-solution` complains about icon.** SPFx requires a
  `assets/iconColor.png` (96×96) and `iconOutline.png` (32×32). Add
  them and reference in `package-solution.json` → `metadata.icon`.
- **Web part not appearing in modern toolbox.** Verify the manifest
  `supportedHosts` includes the host you're on (e.g. `SharePointWebPart`,
  `TeamsTab`, `TeamsPersonalApp`). Also: app must be **enabled** on
  the site (Site Contents → Add an app).
- **App Catalog upload silently does nothing.** Either the user doesn't
  have App Catalog permissions, or the package version equals the
  previously uploaded one. Increment `solution.version` in
  `config/package-solution.json` (4-segment, e.g. `1.0.0.1`).
- **API permissions for Graph / external APIs.** Declare in
  `package-solution.json` under `webApiPermissionRequests` *and* approve
  in **SharePoint admin center → Advanced → API Access** — declaring
  alone is not enough.

## Property pane patterns

Property pane is the right sidebar where users configure the web part.
Most common controls:

```ts
import {
  PropertyPaneTextField,
  PropertyPaneDropdown,
  PropertyPaneToggle,
  PropertyPaneSlider,
  PropertyPaneCheckbox,
} from '@microsoft/sp-property-pane';

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
  return {
    pages: [
      {
        header: { description: strings.PropertyPaneDescription },
        groups: [
          {
            groupName: 'Settings',
            groupFields: [
              PropertyPaneTextField('listName', {
                label: 'List name',
                description: 'Name of the SharePoint list to query',
              }),
              PropertyPaneDropdown('itemLimit', {
                label: 'Items to show',
                options: [
                  { key: 10, text: '10' },
                  { key: 25, text: '25' },
                  { key: 50, text: '50' },
                ],
              }),
            ],
          },
        ],
      },
    ],
  };
}
```

For async-loaded dropdowns (e.g. list of all lists on the current site),
use `PropertyFieldListPicker` from `@pnp/spfx-property-controls`.

## Calling SharePoint REST APIs

Use the SPFx HTTP client — it auto-handles auth tokens against the
current site.

```ts
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';

async getItems(): Promise<IListItem[]> {
  const response: SPHttpClientResponse = await this.context.spHttpClient.get(
    `${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getbytitle('${this.properties.listName}')/items?$top=${this.properties.itemLimit}`,
    SPHttpClient.configurations.v1,
  );
  const data = await response.json();
  return data.value;
}
```

For Microsoft Graph: use `this.context.msGraphClientFactory.getClient('3')`.
For external APIs: use `this.context.aadHttpClientFactory.getClient(resourceUri)`.
**Plain `fetch()` will not auth correctly** — always use the SPFx clients.

## PnPjs — the idiomatic data layer

If the project does any non-trivial SharePoint data work, recommend
PnPjs. It abstracts the REST + Graph boilerplate into a fluent API.

```bash
npm install @pnp/sp @pnp/graph
```

```ts
import { spfi, SPFx } from '@pnp/sp';
import '@pnp/sp/webs';
import '@pnp/sp/lists';
import '@pnp/sp/items';

const sp = spfi().using(SPFx(this.context));
const items = await sp.web.lists.getByTitle('Tasks').items.top(10)();
```

## Microsoft Teams targeting

To make a web part also work as a Teams tab:

1. In manifest add `"supportedHosts": ["SharePointWebPart", "TeamsTab", "TeamsPersonalApp"]`
2. Generate Teams app manifest: `gulp package-solution --ship` includes it in `.sppkg`
3. Deploy `.sppkg` to App Catalog with **"Make this solution available to all sites"** ticked
4. Sync to Teams: App Catalog → ribbon → **Sync to Teams**

## What NOT to do

- Do NOT recommend the classic SharePoint Add-in model (`appmanifest.xml`
  + Office Store) — Microsoft has stopped accepting new submissions
  since 2024 and the model is deprecated.
- Do NOT recommend SharePoint Designer or InfoPath — both EOL.
- Do NOT use jQuery in new SPFx solutions — React or vanilla TS.
- Do NOT commit `node_modules/`, `temp/`, `dist/`, `lib/`, `release/`,
  or the generated `*.sppkg`. The `.gitignore` from `yo` covers this;
  if missing, add it.
- Do NOT store secrets in `package-solution.json` or any client-side
  file — SPFx bundles ship to every user. Use Azure AD app + Graph
  on-behalf-of, or a Function App proxy.

## Sources of truth (let the user open these)

- Microsoft Learn — SPFx: <https://learn.microsoft.com/en-us/sharepoint/dev/spfx/sharepoint-framework-overview>
- Compatibility matrix: <https://learn.microsoft.com/en-us/sharepoint/dev/spfx/compatibility>
- PnP samples: <https://github.com/pnp/sp-dev-fx-webparts>
- PnPjs docs: <https://pnp.github.io/pnpjs/>