MS Teams Channel

Norq compiles Teams templates to Adaptive Card v1.5 JSON. Adaptive Cards (Microsoft's rich message format for Teams) are the standard format for rich messages in Microsoft Teams.

Pipeline: Markdown -> AST (parse tree) -> Adaptive Card JSON

Template files

  • msteams.md -- Markdown mode
  • msteams.json -- Native JSON mode (for inputs, toggles, custom layouts)

Frontmatter

---
enabled: true
---
Field Required Description
enabled No true (default) or false.

Directive compilation

Directive Teams output
:::header TextBlock with ExtraLarge size + Bolder weight
:::footer TextBlock with isSubtle=true, size=Small
:::action Action.OpenUrl entries in the card actions array
:::callout Container with style=accent
:::hero Image element with size=Stretch
:::fields FactSet with title/value facts
:::media Image element; altText from alt attribute
:::columns ColumnSet with Column elements (width=stretch)
:::list TextBlock with list-formatted text
:::raw Parsed JSON inserted as Adaptive Card element

Example

::: header
Order Shipped
:::
 
Hey {{user.first_name}}, your order **#{{order.id}}** has shipped!
 
::: fields
Tracking ID: {{order.tracking_id}}
Delivery: {{order.delivery_date}}
:::
 
::: action
[Track Order]({{tracking_url}}){primary}
:::
 
::: footer
Order notification | {{company_name}}
:::

Compiled output

The output is an Adaptive Card JSON structure:

{
  "card": {
    "type": "AdaptiveCard",
    "version": "1.5",
    "body": [
      {
        "type": "TextBlock",
        "text": "Order Shipped",
        "size": "ExtraLarge",
        "weight": "Bolder"
      },
      {
        "type": "TextBlock",
        "text": "Hey Gaurav, your order **#ORD-123** has shipped!",
        "wrap": true
      },
      {
        "type": "FactSet",
        "facts": [
          { "title": "Tracking ID", "value": "TRK-456" },
          { "title": "Delivery", "value": "Mar 30" }
        ]
      },
      {
        "type": "TextBlock",
        "text": "Order notification | Acme Corp",
        "isSubtle": true,
        "size": "Small"
      }
    ],
    "actions": [
      {
        "type": "Action.OpenUrl",
        "title": "Track Order",
        "url": "https://track.example.com/123"
      }
    ]
  }
}

Native JSON mode

For Adaptive Card features beyond what directives cover (Input.Text, Input.Toggle, Action.Submit, ColumnSet with specific widths), use msteams.json:

{
  "$norq": { "enabled": true },
  "type": "AdaptiveCard",
  "version": "1.5",
  "body": [
    {
      "type": "TextBlock",
      "text": "Rate your delivery",
      "size": "Large",
      "weight": "Bolder"
    },
    {
      "type": "Input.ChoiceSet",
      "id": "rating",
      "label": "How was your experience?",
      "choices": [
        { "title": "Excellent", "value": "5" },
        { "title": "Good", "value": "4" },
        { "title": "Average", "value": "3" }
      ]
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Submit Rating"
    }
  ]
}

Inline formatting

Adaptive Cards support a subset of Markdown:

Markdown Adaptive Card
**bold** Rendered bold
*italic* Rendered italic
[text](url) Hyperlink
- list item Bullet list
1. list item Numbered list

Best practices

  • Adaptive Cards have a payload size limit -- keep cards focused
  • Use :::fields for structured data (renders as FactSet, which looks great in Teams)
  • Use :::raw with Adaptive Card JSON for interactive elements (inputs, choices)
  • Test with norq preview <name> --channel msteams to validate the card structure
  • Action.OpenUrl is the most compatible action type across Teams clients