-
Notifications
You must be signed in to change notification settings - Fork 243
How to extend Link Unfurling template
Zero Install Link Unfurling requires link unfurling app to be published. You need an admin account to publish an app into your org.
Login your admin account in Teams. Go to Manage your apps
-> Upload an app
. Click Upload an app to your org's app catalog
to upload your app's zip file.
Switch to another user account. Without installing this app, paste the link "https://www.botframework.com" into chat box, and you should see the adaptive card like below.
This template removes cache by default to provide convenience for debug. To add cache, REMOVE following JSON part from adaptive card in linkUnfurlingApp.ts
(linkUnfurlingApp.js
):
suggestedActions: {
actions: [
{
title: "default",
type: "setCachePolicy",
value: '{"type":"no-cache"}',
},
],
}
After removing this, the link unfurling result will be cached in Teams for 30 minutes. Please refer to link unfurling document for more details.
The supported types for Zero Install Link Unfurling are "result" and "auth" and this template uses "result" as default. By changing it to "auth", the adaptive card will be:
For card with type "auth", the Teams client strips away any action buttons from the card, and adds a sign in action button. Please refer to zero install link unfurling document for more details.
Stage View is a full screen UI component that you can invoke to surface your web content. You can turn URLs into a tab using an Adaptive Card and Chat Services. Follow the instructions below to add stage view in your link unfurling app.
- Step 1: Update
staticTabs
in manifest.json - Step 2: Update source code
- Step 3: Set
BOT_DOMAIN
andTEAMS_APP_ID
in environment variables - Step 4: Update adaptive card
In appPackage/manifest.json
, update staticTabs
section.
"staticTabs": [
{
"entityId": "stageViewTask",
"name": "Stage View",
"contentUrl": "https://${{BOT_DOMAIN}}/tab",
"websiteUrl": "https://${{BOT_DOMAIN}}/tab",
"searchUrl": "https://${{BOT_DOMAIN}}/tab",
"scopes": [
"personal"
],
"context": [
"personalTab",
"channelTab"
]
}
],
In src/index.ts
(src/index.js
), add following code.
server.get("/tab", async (req, res) => {
const body = `<!DOCTYPE html>
<html lang="en">
<div class="text-center">
<h1 class="display-4">Tab in stage View</h1>
</div>
</html>`;
res.writeHead(200, {
'Content-Length': Buffer.byteLength(body),
'Content-Type': 'text/html'
});
res.write(body);
res.end();
});
For local debug:
Update action file/createOrUpdateEnvironmentFile
in teamsapp.local.yml
, add TEAMS_APP_ID
and BOT_DOMAIN
to env.
- uses: file/createOrUpdateEnvironmentFile # Generate runtime environment variables
with:
target: ./.localConfigs
envs:
BOT_ID: ${{BOT_ID}}
BOT_PASSWORD: ${{SECRET_BOT_PASSWORD}}
TEAMS_APP_ID: ${{TEAMS_APP_ID}}
BOT_DOMAIN: ${{BOT_DOMAIN}}
For remote:
Update infra/azure.parameters.json
. Add following to parameters
:
"teamsAppId":{
"value": "${{TEAMS_APP_ID}}"
}
Add following to infra/azure.bicep
:
param teamsAppId string
resource webAppSettings 'Microsoft.Web/sites/config@2022-09-01' = {
parent: webApp
name: 'appsettings'
properties: {
BOT_DOMAIN: webApp.properties.defaultHostName
BOT_ID: botAadAppClientId
BOT_PASSWORD: botAadAppClientSecret
RUNNING_ON_AZURE: '1'
TEAMS_APP_ID: teamsAppId
WEBSITE_NODE_DEFAULT_VERSION: '~18'
WEBSITE_RUN_FROM_PACKAGE: '1'
}
}
In src/adaptiveCards/helloWorldCard.json
, update actions
to be following.
"actions": [
{
"type": "Action.OpenUrl",
"title": "View Via Deep Link",
"url": "https://teams.microsoft.com/l/stage/${appId}/0?context=%7B%22contentUrl%22%3A%22https%3A%2F%2F${url}%2Ftab%22%2C%22websiteUrl%22%3A%22https%3A%2F%2F${url}%2Ftab%22%2C%22name%22%3A%22DemoStageView%22%7D"
}
],
Run npm install @microsoft/adaptivecards-tools
. This package helps render placeholders such as ${url}
in adaptive card to be real values.
In src/linkUnfurlingApp.ts
(src/linkUnfurlingApp.js
), update variable attachment
to be following.
const data = { url: process.env.BOT_DOMAIN, appId: process.env.TEAMS_APP_ID };
const renderedCard = AdaptiveCards.declare(card).render(data);
const attachment = { ...CardFactory.adaptiveCard(renderedCard), preview: previewCard };
In Teams, the adaptive card will be like:
Opening stage view from Adaptive card via deep link:
In Outlook, the adaptive card will be like:
Opening stage view from Adaptive card via deep link:
Please refer to Stage view document for more details.
Once your link is unfurled into an Adaptive Card and sent in conversation, you can use Task modules to create modal pop-up experiences in your Teams application. Follow the instructions below to add task module in your link unfurling app.
- Step 1: Update adaptive card
- Step 2: Add
handleTeamsTaskModuleFetch
function in handler - Step 3: Add
handleTeamsTaskModuleSubmit
function in handler
In src/adaptiveCards/helloWorldCard.json
, update actions
to be following.
"actions": [
{
"type": "Action.Submit",
"title": "Task module",
"data": {
"msteams": {
"type": "task/fetch",
"data": "task module"
}
}
}
],
For typescript template, in src/linkUnfurlingApp.ts
, add following method to LinkUnfurlingApp
class.
public async handleTeamsTaskModuleFetch(context: TurnContext, taskModuleRequest: TaskModuleRequest): Promise<TaskModuleResponse> {
return {
task: {
type: "continue",
value: {
title: "Task Module Fetch",
height: 200,
width: 400,
card: CardFactory.adaptiveCard({
version: '1.0.0',
type: 'AdaptiveCard',
body: [
{
type: 'TextBlock',
text: 'Enter Text Here'
},
{
type: 'Input.Text',
id: 'usertext',
placeholder: 'add some text and submit',
IsMultiline: true
}
],
actions: [
{
type: 'Action.Submit',
title: 'Submit'
}
]
})
},
},
};
}
For javascript template, in src/linkUnfurlingApp.js
, add following method to LinkUnfurlingApp
class.
handleTeamsTaskModuleFetch(context, taskModuleRequest) {
return {
task: {
type: "continue",
value: {
title: "Task Module Fetch",
height: 200,
width: 400,
card: CardFactory.adaptiveCard({
version: '1.0.0',
type: 'AdaptiveCard',
body: [
{
type: 'TextBlock',
text: 'Enter Text Here'
},
{
type: 'Input.Text',
id: 'usertext',
placeholder: 'add some text and submit',
IsMultiline: true
}
],
actions: [
{
type: 'Action.Submit',
title: 'Submit'
}
]
})
},
},
};
}
For typescript template, in src/linkUnfurlingApp.ts
, add following method to LinkUnfurlingApp
class.
public async handleTeamsTaskModuleSubmit(context: TurnContext, taskModuleRequest: TaskModuleRequest): Promise<TaskModuleResponse> {
return {
task: {
type: 'message',
value: 'Thanks!'
}
};
}
For javascript template, in src/linkUnfurlingApp.js
, add following method to LinkUnfurlingApp
class.
handleTeamsTaskModuleSubmit(context, taskModuleRequest) {
return {
task: {
type: 'message',
value: 'Thanks!'
}
};
}
In Teams, the adaptive card will be like:
Click "Task module" button:
Click "Submit" button:
Please refer to Task module document for more details.
Adaptive Card actions allow users to interact with your card by clicking a button or selecting a choice. Follow the instructions below to add adaptive card action in your link unfurling app.
- Step 1: Update
bots
section in manifest - Step 2: Update adaptive card
- Step 3: Add
onAdaptiveCardInvoke
function in handler
The card action requires bot capability. In appPackage/manifest.json
, update bots
section to be following.
"bots": [
{
"botId": "${{BOT_ID}}",
"scopes": [
"team",
"personal",
"groupchat"
],
"supportsFiles": false,
"isNotificationOnly": false
}
]
In src/adaptiveCards/helloWorldCard.json
, update actions
to be following.
"actions": [
{
"type": "Action.Execute",
"title": "card action",
"verb": "cardAction",
"id": "cardAction"
}
],
For typescript template, in src/linkUnfurlingApp.ts
, add following method to LinkUnfurlingApp
class.
public async onAdaptiveCardInvoke(context: TurnContext, invokeValue: AdaptiveCardInvokeValue): Promise<AdaptiveCardInvokeResponse> {
const card = {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "Your response was sent to the app",
"size": "Medium",
"weight": "Bolder",
"wrap": true
},
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.4"
};
const res = { statusCode: 200, type: "application/vnd.microsoft.card.adaptive", value: card };
return res;
}
For javascript template, in src/linkUnfurlingApp.js
, add following method to LinkUnfurlingApp
class.
onAdaptiveCardInvoke(context, invokeValue) {
const card = {
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "Your response was sent to the app",
"size": "Medium",
"weight": "Bolder",
"wrap": true
},
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.4"
};
const res = { statusCode: 200, type: "application/vnd.microsoft.card.adaptive", value: card };
return res;
}
In Teams, the adaptive card will be like:
Click card action
button, the adaptive card will be updated to be following:
Please refer to Universal actions document for more details.
The Notification, Command and Workflow Bot are scenario templates provided by Teams Toolkit. These templates have similar structure. This guide takes Notification Bot as an example.
Select the Teams Toolkit icon on the left in the VS Code toolbar. Choose "Create a New App"->"Bot"->"Chat Notification Message". Wait for the download complete.
Copy all methods from src/linkUnfurlingApp.ts
class to Notification Bot's empty TeamsActivityHandler
in src/teamsBot.ts
.
Copy composeExtension
section in your appPackage/manifest.json
to Notification bot's appPackage/manifest.json
.
Now your Notification bot project has both notification and link unfurling function.
Build Custom Engine Copilots
- Build a basic AI chatbot for Teams
- Build an AI agent chatbot for Teams
- Expand AI bot's knowledge with your content
Scenario-based Tutorials
- Send notifications to Teams
- Respond to chat commands in Teams
- Respond to card actions in Teams
- Embed a dashboard canvas in Teams
Extend your app across Microsoft 365
- Teams tabs in Microsoft 365 and Outlook
- Teams message extension for Outlook
- Add Outlook Add-in to a Teams app
App settings and Microsoft Entra Apps
- Manage Application settings with Teams Toolkit
- Manage Microsoft Entra Application Registration with Teams Toolkit
- Use an existing Microsoft Entra app
- Use a multi-tenant Microsoft Entra app
Configure multiple capabilities
- How to configure Tab capability within your Teams app
- How to configure Bot capability within your Teams app
- How to configure Message Extension capability within your Teams app
Add Authentication to your app
- How to add single sign on in Teams Toolkit for Visual Studio Code
- How to enable Single Sign-on in Teams Toolkit for Visual Studio
Connect to cloud resources
- How to integrate Azure Functions with your Teams app
- How to integrate Azure API Management
- Integrate with Azure SQL Database
- Integrate with Azure Key Vault
Deploy apps to production