Microsoft SharePoint Framework (SPFx) supports, since version 1.10.0, the ability to create Personal Apps for Microsoft Teams. A Personal App in Microsoft Teams is an App that a user can install and can be accessed through the left rail in the Microsoft Teams App:

Personal Apps in the left rail and under the 3 dots in Microsoft Teams

A Personal App is not connected to a Team or channel and therefor does not have the ability to show the web part configuration pane in order to configure your Personal App. In SPFx web parts displayed as a Tab in a Teams channel, your web parts can be configured just as you are used to in SharePoint itself.

So what are the configuration options?

In my opinion a Personal App can have 2 kinds of configuration options:

  1. Global settings -> settings used in the Personal App, which are the same for each user installing the App
  2. Individual settings -> settings which are personally selected and applicable to an individual user

Global settings

When you need global settings, which are the same for each user, the SharePoint Framework provides the use of ‘SharePoint Online tenant properties‘. These properties are stored in the App catalog and can be read by various SharePoint Framework components. This way you have a central place to manage those settings and an easy way to use them. Global settings could be Url’s to Web APIs you use, SharePoint Url’s and List names containing your data, etc.

SharePoint Online tenant properties can be added using SharePoint Online Management Shell, Office 365 CLI or PnP PowerShell.

When you need to retrieve a SharePoint Online tenant property from your SharePoint Framework components you can make a GET request to the following SharePoint API:

GET _api/web/GetStorageEntity('key')

The result of the API call will be:

HTTP/1.1 200 OK
Content-Type: application/json
{
    "Comment":"Tenant property comment.",
    "Description":"Tenant property description",
    "Value":"Tenant property key value"
}

Individual settings

Personal Apps don’t offer a default way and repository for your individual settings. So when you want to use individual settings for your web part or within your web part, you need to think about where you want to store those settings and how to retrieve them. In my opinion SharePoint would be the most obvious place to store the settings. Of course you could use an external repository in Azure or other place, but using this option always comes with extra things you need to take care of, like authentication for instance. Retrieving information from SharePoint is pretty straightforward and authentication is there already. You could use a central SharePoint List and set the option that users can only view and edit their own items. You can store settings in a custom property in the users User Profile. Another option could be to use the users OneDrive and store a json file in a folder with your web part name. It’s always good to take caching these settings into account and not retrieve them every time you load your Personal App.

PnPjs

One way to retrieve the individual settings is to use PnPjs. PnPjs can easily handle retrieving SharePoint list items, SharePoint User Profile properties of getting an item from the users OneDrive. It has also build in support for handling caching in the users browser (session or local).

SharePoint List items can be retrieved using:

import { sp } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";

// get all the items from a list
const items: any[] = await sp.web.lists.getByTitle("My List").items.get();
console.log(items);

// get a specific item by id
const item: any = await sp.web.lists.getByTitle("My List").items.getById(1).get();
console.log(item);

// use odata operators for more efficient queries
const items2: any[] = await sp.web.lists.getByTitle("My List").items.select("Title", "Description").top(5).orderBy("Modified", true).get();
console.log(items2);

or using a good old Caml query:

import { ICamlQuery } from "@pnp/sp/lists";

// build the caml query object (in this example, we include Title field and limit rows to 5)
const caml: ICamlQuery = {
    ViewXml: "<View><ViewFields><FieldRef Name='Title' /></ViewFields><RowLimit>5</RowLimit></View>",
};

// get list items
const r = await list.getItemsByCAMLQuery(caml);

// log resulting array to console
console.log(r);

SharePoint User Profile property can be retrieved using:

const loginName = "i:0#.f|membership|testuser@mytenant.onmicrosoft.com";
const propertyName = "AccountName";
const property = await sp.profiles.getUserProfilePropertyFor(loginName, propertyName);
console.log(property);

Users OneDrive item can be retrieved using:

import { graph } from "@pnp/graph";

const search = await graph.users.getById('user@tenant.onmicrosoft.com').drives.getById('driveId')root.search('queryText').get();

const search = await graph.me.drives.getById('driveId')root.search('queryText').get();

The PnPjs oData caching can be used in combination with above queries:

import { sp } from "@pnp/sp";

const r = await sp.web.lists.getByTitle("Tasks").items.usingCaching().get();
console.log(r);

const r2 = await sp.web.lists.getByTitle("Tasks").items.top(5).orderBy("Modified").usingCaching().get();
console.log(r2);

Next to retrieving the settings from your repository, you are also responsible for the user interface for configuring these settings. So for instance you need to add a settings button, which will open an Office UI Fabric side panel where you can configure your settings.

Summary

Building Personal Apps for Microsoft Teams using the SharePoint Framework (SPFx) is a great way to extend Teams and incorporate your business processes in Teams. Personal Apps don’t have an out of the box way for holding and setting configuration settings. This is up to the developer building the Personal App. This blog showed some configuration options you could use when using SPFx. I am curious what configuration options you use within your Personal Apps built with the SharePoint Framework. Please leave a comment below if you have other ways to do this!