Forge's EAP offers experimental features to selected users for testing and feedback purposes. These features are unsupported and not recommended for use in production environments. They are also subject to change without notice. For more details, see Forge EAP, Preview, and GA.
To participate, you can sign up for the EAP here.
Note: You must also opt-in to the open beta of Dashboards in Atlassian Home. See the guide on how to opt-in.
The dashboard widget module allows you to create interactive widgets that can be added to the dashboards in Atlassian Home. These widgets can:

Example of a dashboard widget displaying custom content
You can create a dashboard widget app with the following steps:
forge create and follow the prompts, selecting the templates under Dashboards (EAP).forge deploy to deploy the app.forge install and follow the prompts to install the app to Jira context (even though it is only available in Atlassian Home).When users install your widget to their site, they'll see your widget in the widget list:

Widget selection interface showing available dashboard widgets on the right, and on the left showing the preview of the selected dashboard widget
Users can configure your widget through the edit interface:

Widget configuration interface allowing users to customize widgets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16modules: dashboards:widget: - key: hello-world-widget title: Hello World Widget description: A sample dashboard widget thumbnail: https://example.com/icon.svg resource: widgetResource edit: resource: widgetEditResource resources: - key: widgetResource path: static/widget/build - key: widgetEditResource path: static/widget-edit/build
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28modules: dashboards:widget: - key: hello-world-widget-ui-kit title: Hello World Widget (UI Kit) description: A sample dashboard widget using UI Kit thumbnail: https://example.com/icon.svg resource: widgetResource render: native resolver: function: widgetResolver edit: resource: widgetEditResource render: native resolver: function: widgetEditResolver resources: - key: widgetResource path: static/widget/build - key: widgetEditResource path: static/widget-edit/build functions: - key: widgetResolver handler: widgetResolver.handler - key: widgetEditResolver handler: widgetEditResolver.handler
| Property | Type | Required | Description |
|---|---|---|---|
key | string | Yes | A key for the module, which other modules can refer to. Must be unique within the manifest. |
title | string | Yes | The title of the widget as displayed to users. |
description | string | Yes | A description of what the widget does. |
thumbnail | string | Yes | The absolute URL of the icon displayed next to the widget's name and description. |
resource | string | Yes | The key of a static resources entry that provides the widget view. |
edit | object | No | Configuration for the widget's edit mode. |
aiContext | object | No | Configuration that lets the widget contribute structured data to AI insights. See aiContext object properties. |
| Property | Type | Required | Description |
|---|---|---|---|
resource | string | Yes | The key of a static resources entry that provides the widget edit experience. |
| Property | Type | Required | Description |
|---|---|---|---|
data | object | Yes | Points at the function (or remote endpoint) that returns the widget's data for AI insights. Provide exactly one of function or endpoint. |
| Property | Type | Required | Description |
|---|---|---|---|
function | string | Conditional | The key of a function that resolves the AI context payload. Mutually exclusive with endpoint. |
endpoint | string | Conditional | The key of a remote endpoint that resolves the AI context payload. Mutually exclusive with function. |
Chart and dashboard insights are part of a separate EAP from the dashboard widget module. To
contribute your widget's data to insights through aiContext.data, you must also sign up for
the insights EAP.
Dashboard widgets can contribute a structured, tabular view of their data to Atlassian
Intelligence insights. The platform invokes the aiContext.data entry point declared
on your module and passes the response to the AI as prompt context. This data powers both:
The platform sends data your widget returns from aiContext.data to a generative AI model
to produce insights. Only return data that's appropriate to process with AI, and ensure you
comply with the Atlassian Acceptable Use Policy.
Insights only render when AI is enabled for Jira. If it's not enabled, the
aiContext.data entry point isn't invoked.
Add an aiContext block to your dashboards:widget module and point its data field at
a function (or a remote
endpoint):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23modules: dashboards:widget: - key: hello-world-widget title: Hello World Widget description: A sample dashboard widget thumbnail: https://example.com/icon.svg resource: widgetResource edit: resource: widgetEditResource aiContext: data: function: aiContextResolver resources: - key: widgetResource path: static/widget/build - key: widgetEditResource path: static/widget-edit/build functions: - key: aiContextResolver handler: aiContext.handler
The referenced function must return an object matching the return-value schema. For a full handler example, see AI insights context data in the Examples section.
Your response must be an object with the following fields:
| Field | Type | Required | Notes |
|---|---|---|---|
title | string | No | Title for the data. Defaults to the widget's manifest title if omitted. Used by both chart and dashboard insights. |
type | string | No | Free-form chart type (for example, 'bar', 'line', 'pie'). Surfaced to the AI for prompt context. |
description | string | No | Natural-language description of the widget or data. Defaults to the widget's manifest description if omitted. Consumed by dashboard insights only; chart insights don't use this field. |
columns |
Array<{key: string;label: string;}>
| Yes | key is the stable field id used to read object rows (row[key]); label is the human-readable header shown to the AI. |
rows |
Array<Cell[] |Partial<Record<string, Cell>>>
| Yes | Each row is either a positional array aligned to the columns order, or an object keyed by column key. |
A cell is a string, number, boolean, or null.
Import the response type from @forge/dashboards-bridge to type your function:
1 2import type { ForgeAiContextResponse } from "@forge/dashboards-bridge";
ForgeAiContextResponse optionally accepts a union of column keys. For example,
ForgeAiContextResponse<'issue_type' | 'count'> keeps your columns and object-row keys
in agreement.
JSON.stringify of the whole payload).
This keeps the prompt within the model's context window.If you exceed either limit, the platform rejects the response and the widget's data isn't used for insights.
For detailed API documentation, see:
Use the Dashboard bridge APIs and dashboard hooks for widget development.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25import React, { useEffect, useState } from "react"; import { useWidgetConfig, useWidgetContext } from "@forge/hooks/dashboards"; import { widget } from "@forge/dashboards-bridge"; // Set preview configuration widget.setPreviewConfig({ title: "Sample Title", }); export const DashboardWidget = () => { const { config } = useWidgetConfig(); const { layout } = useWidgetContext(); return ( <div> <div>{config?.title || "Default Title"}</div> <div> Size: {layout?.width}x{layout?.height} </div> </div> ); }; export default DashboardWidget;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33import React from "react"; import { useWidgetConfig } from "@forge/hooks/dashboards"; import { widgetEdit } from "@forge/dashboards-bridge"; // Set up save handlers widgetEdit.onSave(async (config, { widgetId }) => { console.log("Widget saved!", config, widgetId); }); widgetEdit.onProductSave(async (config) => { console.log("Widget config before saving in-product!", config); return null; // return config to opt-in to in-product save }); const WidgetEditMode = () => { const { config, updateConfig } = useWidgetConfig(); return ( <input type="text" placeholder="Widget Title" value={config?.title} onChange={(e) => { updateConfig({ title: e.target.value, }); }} /> ); }; export default WidgetEditMode;
The function referenced by aiContext.data returns a structured,
tabular view of the widget's data for AI insights. The following example mixes both
supported row styles: a positional array aligned to columns, and an object keyed by
column key:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16export const handler = async () => { return { title: "Issues by type", type: "bar", description: "Breakdown of open issues by type", columns: [ { key: "issue_type", label: "Issue Type" }, { key: "count", label: "Count" }, ], rows: [ ["Bug", 25], // positional array, aligned to the columns order { issue_type: "Story", count: 40 }, // object keyed by column key ], }; };
Rate this page: