{"id":16319464,"url":"https://github.com/josverl/powertab","last_synced_at":"2025-08-03T10:10:09.817Z","repository":{"id":94789462,"uuid":"226974347","full_name":"Josverl/PowerTab","owner":"Josverl","description":"Teams App with a configurable PowerApp tab with Teams context ","archived":false,"fork":false,"pushed_at":"2021-04-13T02:39:15.000Z","size":9570,"stargazers_count":2,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-30T09:14:11.215Z","etag":null,"topics":["deeplink","powerapps","powerapps-solutions","teams","teams-sdk"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Josverl.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-12-09T21:47:57.000Z","updated_at":"2021-04-13T02:39:17.000Z","dependencies_parsed_at":null,"dependency_job_id":"f64a2c81-1665-4920-af89-349e658f8dce","html_url":"https://github.com/Josverl/PowerTab","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Josverl/PowerTab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Josverl%2FPowerTab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Josverl%2FPowerTab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Josverl%2FPowerTab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Josverl%2FPowerTab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Josverl","download_url":"https://codeload.github.com/Josverl/PowerTab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Josverl%2FPowerTab/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268526368,"owners_count":24264408,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deeplink","powerapps","powerapps-solutions","teams","teams-sdk"],"created_at":"2024-10-10T22:27:04.390Z","updated_at":"2025-08-03T10:10:09.803Z","avatar_url":"https://github.com/Josverl.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PowerTab, (a PowerApp better integrated in a Teams Tab)\n\nGenerating a Teams app [from a PowerApp is simple](https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/embed-teams-app), right ?  \nUnfortunately after adding such a `Teamsified` PowerApp to your Team and Channel, the resulting _Teams Power App_ is pretty static, and it is not aware of the Team or Channel (or Chat) it is pinned to.\nAnd as such you may need to add additional configuration and navigation, or perhaps even create and maintain multiple copies of your PowerApp.\n\nThis can be done a little smarter, by configuring Teams to pass the relevant information as query string parameters to your Power App\nusing [url placeholder values](https://docs.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context#getting-context-by-inserting-url-placeholder-values).  \nNote:  Additional context parameters are/may be documented as part of the [javascript sdk Teams Context](https://docs.microsoft.com/en-us/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest). \n\nThen you can add a little logic to the PowerApp to read and make use of this information.\n\nAs of march 2020 this is now a standard feature in PowerApps , but not please read on if you want to add addintional context variables in your app manifest.\n\nThis can be achieved by using a custom configuration page, that takes the PowerApp Application ID, and performs the relevant configuration so that Teams will pass the relevant information to your PowerApp.\nThis page is only involved during the initial configuration, after this its just Teams and your PowerApp (with some additional information)  \nThe relevant context information includes this such as : \n* The Teams ID and Teams Display Name \n* The channel ID and Channel Display Name\n* The theme (dark, light, accessible) \n\n## Use cases \n\n- Display the Teams and Channel name\n- use the Theme to determine when to render a high contrast UX  \n- use the Teams ID \n- Use the entity ID in a deeplink to show information regarding a specific  Mention \n\n## General steps :\n1. Create a PowerApp\n2. Save \u0026 Publish your PowerApp \n3. Download the Teams manifest for your PowerApp \n4.  Import and Open the Teams App Manifest in [Teams App Studio](https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/app-studio-overview#manifest-editor) \n5. Change the Teams app manifest to to change the configurable tab as in the below section\n6. Use the PowerTab configuration page to configure which parameters you want to pass to your PowerApp\n7. Retrieve the teams context parameters in PowerApp \n8. Use this Teams context in your PowerApp to drive an even better user and collaboration experience      \n\nOne example it to use the teams Context information to create a [Deeplink](Deeplinks.md) to your tab,  \nthat you can send in a adaptive card. That deeplink will allow the recipient to return directly to your tab, and can optionally include relevant information on their action / response in the subEntityID\n\n## Teams manifest - Team tab (a.k.a. Configurable Tab) \n\nYou should create or change a Teams manifest to use the PowerTab config page hosted as the PoC or to your own copy.\nConfiguration page: `https://powertab.azurewebsites.net/config.html?PowerAppId=\u003cID_Of_Your_PowerApp\u003e`\n\nafter the change it should look something like this:  \n![manifest editor showing Tab configuration](img/configured_teams_tab.png)\n\nExample [Manifest](manifest/manifest.json)\n\n\n# Live PowerTab site \nfor demos and Proof of concepts feel free to use the live configuration page located at:\nhttps://powertab.azurewebsites.net/config.html\n\n**Note: If you use the PoC page, please be aware it has limited capacity and may change or stop working with no prior notice.**\n## PowerApp onStart or onLoad\n\nIn PowerApp you can retrieve the Teams context, and store them in a global variable using the Param function `Param(\"TeamId\")`.\nAs there may be cases when the PowerApp is started outside of Teams, you can use the Coalesce function to supply a sensible default  \n\nBelow is a sample to store the teams context in a single global variable (a record) \nso that you can retrieve the Teams Displayname as `glbTeamsContext.teamName`\n\n`PowerApp App.OnStart: `\n``` PowerApp \n// If specified, the Teams App ID can be used to generate deeplinks to this Tab\nSet(TeamsAppID, \"12345678-1234-1234-1234-123456789ABC\");\n\n// get Teams context in App.OnStart as a single record / variable\nSet(\n    glbTeamsContext,\n    {\n        source: Coalesce(Param(\"source\"), \"web\"),\n        groupId: Coalesce(Param(\"groupId\"), \"00000000-0000-0000-0000-000000000000\"),\n        teamId: Coalesce(Param(\"teamId\"), \"19:[team-id]@thread.skype\"),\n        channelId: Coalesce( Param(\"channelId\"), \"19:[channel-id]@thread.skype\"),\n        teamName: Coalesce( Param(\"teamName\"), \"Team unknown\"),\n        channelName: Coalesce( Param(\"channelName\"), \"Channel unknown\"),\n        chatId: Coalesce( Param(\"chatId\"), \"19:[chat-id]@thread.skype\"),\n\n        theme: Coalesce( Param(\"theme\"), \"light\"),\n\n        channelType: Coalesce( Param(\"channelType\"), \"\"),\n        teamSiteUrl: Coalesce( Param(\"teamSiteUrl\"), \"\"),\n\n        locale: Coalesce( Param(\"locale\"), \"\"),\n        entityId: Coalesce( Param(\"entityId\"), \"\"),\n        subEntityId: Coalesce( Param(\"subEntityId\"), \"\"),\n        \n        tid: Coalesce( Param(\"tid\"), \"\"),\n        isFullScreen: Coalesce( Param(\"isFullScreen\"), \"\"),\n        userLicenseType: Coalesce( Param(\"userLicenseType\"), \"\"),\n        tenantSKU: Coalesce( Param(\"tenantSKU\"), \"\")\n    }\n); \n```\n_Note: The parameters names are case sensitive._\n\n\n**Alternatively you can just retrieve a few specific parameters.**\n``` PowerApp \n// get Teams context from the QueryString in App.OnStart\nSet( glbsource, Param(\"source\"));\nSet( glbTeamId, Param(\"teamId\"));\nSet( glbChannelID, Param(\"channelId\"));\nSet( glbTheme, Param(\"theme\") , \"light\"));\n\n```\n\n\n\n## Best option to create a PowerApp for embedding in Teams \n\nfor best results : \n- Start in a Teams channel\n- Add a Tab,\n- Select PowerApps \n- Click the link at the bottom : `Or create an app in Power Apps` \n![image of link in Teams to create PowerApp ](./img/create_in_PowerApps.png)\n\nThis will start a PowerApp that has the additional benefits of \n- A **Teams Purple theme** for your PowerApp \n- **Automatic scaling / adjustment** of the screen size\n\n# The Details \n\n## Teams Tab configuration \n\nThe following configuration is saved for the Tab: \n - **contentUrl: getUrl(idPowerApp, true)**  \n   This is the complete url to run the PowerApp in context of Teams, so this includes all the Teams replacement tokens that have been selected.  \n    - contentUrl: `https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/b78d9c7e-9e44-4217-9cf3-f46dd4be475f?source=teamstab\u0026groupId={groupId}\u0026teamId={teamId}\u0026channelId={channelId}\u0026chatId={chatId}\u0026theme={theme}\u0026teamSiteUrl={teamSiteUrl}` \n\n\n - **websiteUrl: getUrl(idPowerApp, false)**  \n   This is the complete url to run the PowerApp in a browser. This does not includes any of the Teams context replacement tokens, as they would not be replaced with the actual teams context. To allow an App to determine how it is opened, the only query string parameter provided is : `source=teamsopenwebsite`\n\n    - websiteUrl: `https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/b78d9c7e-9e44-4217-9cf3-f46dd4be475f?source=teamsopenwebsite`\n\n - **entityId: idPowerApp**  \n    the PowerApp ID (a GUID)\n\n - suggestedDisplayName: \"PowerTab\"  \n    The default name for the Tab \n\n\n## Most supported URL parameters \n\nParameters :\n - \"teamName\": \"The name of the current team\",\n - \"channelId\": \"The channel ID in the format 19:[id]@thread.skype\",\n - \"channelName\": \"The name of the current channel\",\n - \"chatId\": \"The chat ID in the in the format 19:[id]@thread.skype\",\n - \"locale\": \"The current locale of the user formatted as languageId-countryId (for example, en-us)\",\n - \"entityId\": \"The developer-defined unique ID for the entity this content points to. (the PowerApp ID )\",\n - \"subEntityId\": \"The developer-defined unique ID for the sub-entity this content points to\",\n - \"loginHint\": \"A value suitable as a login hint for Azure AD. This is usually the login name of the current user, in their home tenant\",\n - \"userPrincipalName\": \"The User Principal Name of the current user, in the current tenant\",\n - \"userObjectId\": \"The Azure AD object id of the current user, in the current tenant\",\n - \"tid\": \"The Azure AD tenant ID of the current user\",\n - \"groupId\": \"Guid identifying the current O365 Group ID\",\n - \"theme\": \"The current UI theme: default | dark | contrast\",\n - \"isFullScreen\": \"Indicates whether the tab is in full-screen mode\",\n - \"userLicenseType\": \"Indicates the user licence type in the given SKU (for example, student or teacher)\",\n - \"tenantSKU\": \"Indicates the SKU category of the tenant (for example, EDU)\",\n - \"channelType\": \"microsoftTeams.ChannelType.Private | microsoftTeams.ChannelType.Regular\" --\u003e\n\nNotes:  \n- Parameter names are the same for Teams as for the PowerApp\n- camelCasing may lead to mistakes, as the url string parameters are Case sensitive.\n\n#### References:\n\n- [Teams Context URL Placeholders](https://docs.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context#getting-context-by-inserting-url-placeholder-values)\n- [Teams Context URL Placeholders - Private Channels](https://docs.microsoft.com/en-us/microsoftteams/platform/tabs/how-to/access-teams-context#retrieving-context-in-private-channels)\n- [Teams SDK - Context](https://docs.microsoft.com/en-us/javascript/api/@microsoft/teams-js/microsoftteams.context?view=msteams-client-js-latest)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosverl%2Fpowertab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjosverl%2Fpowertab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjosverl%2Fpowertab/lists"}