SharePointVault ~/gotchas/spfx ⌕ Search 404 pages, error messages, scripts…Ctrl K ★ Star
M↓ README.mdM↓ teams-personal-app-needs-global-deploy.md
sharepoint-vault›gotchas›spfx›teams-personal-app-needs-global-deploy.mdhistoryedit on GitHub
● GOTCHAspfx· 3 min read

SPFx in Teams: a personal app needs global deployment, not a root-site install

applies to: SharePoint Online (SPFx 1.18+, Teams)reviewed: 2026-07-16#spfx#teams#deployment#app-catalog

A Teams personal app hosts your web part on the tenant root site, so it needs global deployment (skipFeatureDeployment: true plus make available to all sites) and a teams/ folder with correctly named icons — miss either and you get the componentType crash or no Teams app at all.

Osobní Teams appka hostuje tvůj webpart na kořenovém webu tenantu, takže potřebuje globální nasazení (skipFeatureDeployment: true a zpřístupnění všem webům) a složku teams/ se správně pojmenovanými ikonami – bez jednoho z toho dostaneš pád na componentType, nebo se Teams appka vůbec neobjeví.

Symptom

Your SPFx web part works as a Teams channel tab but the personal app crashes on load:

Cannot destructure property 'componentType' of 'this.context.webPartManifest'

Or more confusingly: one of your apps shows up in Teams and another — packaged seemingly the same way — doesn't appear in the Teams catalog at all.

Cause

Two separate mechanisms, both convention-driven and neither obvious:

  1. Teams catalog publication is triggered by a teams/ folder in the project root containing two icons — no config entry anywhere:
    • teams/<webPartComponentId>_color.png — 192 × 192 tile,
    • teams/<webPartComponentId>_outline.png — 32 × 32 transparent white silhouette,
    • where <webPartComponentId> is the web part's manifest id — not solution.id. Wrong GUID → silently no Teams app. Plus supportedHosts must include "TeamsTab" / "TeamsPersonalApp".
  2. A personal app hosts your SPFx code on the tenant root site (/_layouts/15/teamshostedapp.aspx). The component must therefore be available on the root site — which is what global deployment does: "skipFeatureDeployment": true in package-solution.json and ticking "Make this solution available to all sites in the organization" at upload. Without it, the root site has no component registration → the componentType destructure crash. (Manually installing the app on the root site "fixes" it too — but that's a fragile workaround that also runs your provisioning on the tenant root. Don't.)

Fix

For any solution meant to run as a Teams personal app:

// package-solution.json
"skipFeatureDeployment": true
  • Upload → tick make available to all sites.
  • Add the teams/ folder with correctly named icons.
  • Overlays/panels: Teams has no 48 px SharePoint suite bar — position them with a host-aware top offset (SP = 48, Teams = 0) instead of a hardcoded top: 48.

Notes

  • Application Customizer widgets (floating buttons etc.) reach every site through a Tenant-Wide Extension: sharepoint/assets/ClientSideInstance.xml in the feature's elementManifests (the Properties attribute is mandatory, may be empty). SharePoint writes its row into the Tenant Wide Extensions list only when the admin ticks Make this solution available to all sites in the organization — without the tick the widget is on no site, and nothing warns you. A site-level UserCustomAction that the app creates itself works with skipFeatureDeployment: true as well (measured on a site with the app installed), so keep it for tenants that don't tick the box and skip it where the solution is deployed tenant-wide (details). "Loaded tenant-wide" just means the code loads everywhere — control actual visibility with runtime checks, defaulting to a silent no-op.
  • With skipFeatureDeployment: true, Feature-framework provisioning XML is ignored — anything you provision must be runtime code.
  • Diagnostic shortcut: opening teamshostedapp.aspx directly in a browser ending in "No Parent window found" is a good sign (component resolved, just no Teams shell). The componentType error is the bad one. Careful, though — outside Teams that page still mounts the web part and runs onInit, including any provisioning, against the tenant root. Not a playground.
  • Re-uploading an updated .sppkg: don't re-tick "make available to all sites" a second time for tenant-wide extensions — you'll get duplicate entries in the Tenant Wide Extensions list.
  • Teams clients (especially mobile) cache app icons hard — after changing them, the admin catalog updates quickly, devices may need a Teams cache clear.
Was this helpful?ask or add your experience on GitHub →
Saved you an hour? A star on GitHub helps other SharePoint people find the vault.★ Star on GitHub
last reviewed: 2026-07-16last updated: 2026-09-25historyedit on GitHubview source