Skip to content

Dashboards

Bridge Town dashboards are self-contained HTML pages generated from a successfully completed model run. Each dashboard is backed by a single key in the run’s outputs dict — the same dict your model writes to /outputs/ during execution. The HTML is stored in S3 and can be viewed inside the web app or shared with project collaborators via an authenticated link.

  • A Bridge Town account with at least one project
  • A model that writes chart-compatible data to /outputs/
  • At least Editor access to the project (to create dashboards)
  • A Pro subscription (to generate shareable links)
Model run succeeds
Outputs dict contains chart data under a named key
create_dashboard(project, dashboard_name, chart_type, model_run_id, output_key)
HTML generated (Plotly or AG Grid) → uploaded to S3 → Dashboard record saved
share_dashboard(project, dashboard_name) → authenticated app URL (collaborators only)

Step 1 — Write chart-compatible output in your model

Section titled “Step 1 — Write chart-compatible output in your model”

During a model run, anything your script writes to /outputs/<filename> is collected into the run’s outputs dict. Dashboard creation reads one key from that dict, so you must produce data that matches the schema for your chosen chart type.

The output_key parameter in create_dashboard is the full filename (including the .json extension) that you wrote to /outputs/.

Call list_chart_types to see every supported chart and its required schema:

{
"name": "list_chart_types",
"arguments": {}
}

Response:

{
"chart_types": [
{
"name": "bar",
"description": "Vertical bar chart — compare values across categories.",
"required_keys": ["categories", "values"],
"example_schema": "{\"categories\": [...], \"values\": [...], \"series_name\"?: \"Value\"}"
},
{
"name": "line",
"description": "Line chart over time — single series or multi-series trend.",
"required_keys": ["x"],
"example_schema": "{\"x\": [...], \"y\": [...]} or multi-series {\"x\": [...], \"series\": [{\"name\": \"...\", \"values\": [...]}]}"
},
{
"name": "table",
"description": "Sortable Plotly table — columnar data with row values.",
"required_keys": ["columns", "rows"],
"example_schema": "{\"columns\": [\"Col1\", ...], \"rows\": [[v1, v2, ...], ...]}"
},
{
"name": "waterfall",
"description": "Bridge/waterfall chart — shows cumulative positive/negative changes; last element is always rendered as the running total.",
"required_keys": ["labels", "values"],
"example_schema": "{\"labels\": [...], \"values\": [...]} (last element rendered as total)"
},
{
"name": "revenue_waterfall",
"description": "FP&A waterfall chart with Bridge Town colour palette — revenue bridge from start to end; last element rendered as total.",
"required_keys": ["labels", "values"],
"example_schema": "{\"labels\": [...], \"values\": [...]} (last element rendered as total)"
},
{
"name": "expense_breakdown",
"description": "Horizontal bar chart of expense categories — sorted largest to smallest.",
"required_keys": ["categories", "values"],
"example_schema": "{\"categories\": [...], \"values\": [...], \"series_name\"?: \"Expense\"}"
},
{
"name": "headcount_timeline",
"description": "Headcount trend line — single series or stacked multi-series breakdown.",
"required_keys": ["x"],
"example_schema": "{\"x\": [...], \"y\": [...]} or {\"x\": [...], \"series\": [{\"name\": \"...\", \"values\": [...]}], \"stacked\"?: true}"
},
{
"name": "cash_flow_projection",
"description": "Actual vs projected cash flow — months on the x-axis; either 'actual' or 'projected' series may be omitted for months where unavailable.",
"required_keys": ["months"],
"example_schema": "{\"months\": [...], \"actual\"?: [...], \"projected\"?: [...]}"
},
{
"name": "data_grid",
"description": "Interactive AG Grid table — supports sorting, filtering, and CSV export. Accepts object rows or simplified array rows.",
"required_keys": ["columns", "rows"],
"example_schema": "{\"columns\": [{\"field\": \"Name\", \"type\"?: \"text|number|date\"}, ...], \"rows\": [{...}]} or simplified {\"columns\": [\"Name\", ...], \"rows\": [[\"Alice\", ...], ...]}"
}
],
"count": 9
}

Once you have a successful run with compatible output, call create_dashboard.

Model output (/outputs/quarterly_revenue.json):

{
"categories": ["Q1", "Q2", "Q3", "Q4"],
"values": [1200000, 1350000, 1500000, 1800000],
"series_name": "Revenue"
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "forecasts",
"dashboard_name": "Q4 Revenue",
"chart_type": "bar",
"model_run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"output_key": "quarterly_revenue.json",
"description": "Quarterly revenue breakdown",
"subtitle": "FY2026",
"currency": "USD"
}
}

Response:

{
"dashboard_id": "d1e2f3a4-b5c6-7890-def1-234567890abc",
"dashboard_name": "Q4 Revenue",
"project": "forecasts",
"chart_type": "bar",
"model_run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"has_html": true,
"created": true,
"created_at": "2026-04-28T10:00:00+00:00",
"updated_at": "2026-04-28T10:00:00+00:00"
}

Model output (/outputs/plan_vs_actual.json):

{
"columns": ["Metric", "Budget", "Actual", "Variance"],
"rows": [
["Revenue", 5000000, 5200000, 200000],
["COGS", 2000000, 2100000, -100000],
["Gross Profit", 3000000, 3100000, 100000],
["OpEx", 1500000, 1450000, 50000],
["Net Income", 1500000, 1650000, 150000]
]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "forecasts",
"dashboard_name": "P&L Summary",
"chart_type": "table",
"model_run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"output_key": "plan_vs_actual.json",
"currency": "USD"
}
}

Model output (/outputs/headcount.json):

{
"x": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
"series": [
{"name": "Engineering", "values": [30, 32, 35, 38, 40, 42]},
{"name": "Sales", "values": [10, 12, 12, 14, 16, 18]},
{"name": "G&A", "values": [5, 5, 6, 6, 6, 7]}
]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "hr-planning",
"dashboard_name": "Headcount Trend",
"chart_type": "line",
"model_run_id": "b2c3d4e5-f6a7-8901-bcde-f2345678901b",
"output_key": "headcount.json",
"subtitle": "H1 2026"
}
}

Model output (/outputs/revenue_bridge.json):

{
"labels": ["Opening ARR", "New ARR", "Expansion", "Churn", "Closing ARR"],
"values": [5000000, 1500000, 500000, -300000, 6700000]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "forecasts",
"dashboard_name": "ARR Bridge",
"chart_type": "revenue_waterfall",
"model_run_id": "c3d4e5f6-a7b8-9012-cdef-3456789012cd",
"output_key": "revenue_bridge.json",
"currency": "USD"
}
}

Cash flow projection (/outputs/cash_flow.json):

{
"months": ["Jan", "Feb", "Mar", "Apr"],
"actual": [100000, 120000, null, null],
"projected": [null, null, 130000, 140000]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "forecasts",
"dashboard_name": "Cash Flow",
"chart_type": "cash_flow_projection",
"model_run_id": "d4e5f6a7-b8c9-0123-defa-4567890123de",
"output_key": "cash_flow.json",
"currency": "USD"
}
}

Model output (/outputs/customers.json):

{
"columns": [
{"field": "Name", "type": "text"},
{"field": "ARR", "type": "number"},
{"field": "Renewal Date", "type": "date"}
],
"rows": [
{"Name": "Acme Corp", "ARR": 240000, "Renewal Date": "2026-06-15"},
{"Name": "Globex", "ARR": 120000, "Renewal Date": "2026-09-01"}
]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "sales",
"dashboard_name": "Customer List",
"chart_type": "data_grid",
"model_run_id": "e5f6a7b8-c9d0-1234-efab-5678901234ef",
"output_key": "customers.json"
}
}

For P&L grids and financial tables, use column type "currency" on monetary columns. Currency-formatted columns display values like $98,040 while keeping underlying values numeric — sorting, filtering, and CSV export all operate on the raw number. Plain "number" columns (headcount, units, rates) are not currency-formatted.

Model output (/outputs/pnl_table.json):

{
"columns": [
{"field": "Line item", "type": "text"},
{"field": "Year 1", "type": "currency"},
{"field": "Year 2", "type": "currency"},
{"field": "Seats", "type": "number"}
],
"rows": [
{"Line item": "Revenue", "Year 1": 98040, "Year 2": 441180, "Seats": 12},
{"Line item": "EBITDA", "Year 1": -205686, "Year 2": -415586, "Seats": 12}
]
}

Tool call:

{
"name": "create_dashboard",
"arguments": {
"project_name": "dardasha",
"dashboard_name": "3-Year P&L",
"chart_type": "data_grid",
"currency": "USD",
"model_run_id": "a2cb65c6-0dba-4acb-949c-8ba2951fef7d",
"output_key": "pnl_table.json"
}
}

The Year 1 and Year 2 columns render as $98,040 and ($205,686) respectively. The Seats column renders as a plain number.

Use list_dashboards to see what has already been created for a project:

{
"name": "list_dashboards",
"arguments": {
"project_name": "forecasts"
}
}

Response:

{
"project": "forecasts",
"dashboards": [
{
"name": "Q4 Revenue",
"description": "Quarterly revenue breakdown",
"is_shared": false,
"has_html": true,
"created_at": "2026-04-28T10:00:00+00:00",
"updated_at": "2026-04-28T10:00:00+00:00"
},
{
"name": "ARR Bridge",
"description": null,
"is_shared": true,
"has_html": true,
"created_at": "2026-04-27T14:30:00+00:00",
"updated_at": "2026-04-27T16:00:00+00:00"
}
],
"count": 2
}

Call share_dashboard to mark the dashboard as shared and get an authenticated link:

{
"name": "share_dashboard",
"arguments": {
"project_name": "forecasts",
"dashboard_name": "ARR Bridge"
}
}

Response:

{
"dashboard_id": "d1e2f3a4-b5c6-7890-def1-234567890abc",
"dashboard_name": "ARR Bridge",
"project": "forecasts",
"dashboard_url": "https://app.bridgetown.builders/projects/forecasts/dashboards/d1e2f3a4-b5c6-7890-def1-234567890abc",
"access_note": "This URL requires the recipient to be a project collaborator on 'forecasts' with a Bridge Town account. No anonymous access is granted."
}

The dashboard_url takes the recipient directly to the dashboard inside the Bridge Town web app. Recipients must be project collaborators — anyone without a Bridge Town account or project access will be denied. To add a collaborator, use add_collaborator or go to Settings → Team in the web app.

The Bridge Town web app provides a first-class dashboard experience alongside the MCP tools.

After logging in, navigate to Dashboards in the sidebar. The gallery page (/dashboards) lists every dashboard saved by your tenant, ordered by most-recently updated first. Each card shows:

  • Dashboard name and description
  • Whether the dashboard has rendered HTML (has_html)
  • Whether it has been shared (is_shared)
  • Creation and update timestamps

Click any card to open the full-screen viewer. A delete action is available on each card.

Dashboard viewer (/projects/{project}/dashboards/{id})

Section titled “Dashboard viewer (/projects/{project}/dashboards/{id})”

The viewer page fetches the dashboard HTML from S3 (authenticated via the app session) and renders it in a sandboxed iframe:

  • allow-scripts is required for Plotly interactivity
  • allow-popups lets linked drill-downs open in new tabs
  • Navigation and form submission are blocked

If the dashboard HTML has not been generated yet, or if S3 is not configured, the page shows an error state with a link back to the gallery.

Links returned by share_dashboard route through the authenticated Bridge Town web app. Recipients without a Bridge Town account or project access see a sign-in prompt and are denied entry after authentication if they are not a project collaborator.

To revoke access, remove the user from project collaborators in Settings → Team. Deleting the dashboard removes access for everyone.

ActionRequired accessPlan restriction
list_chart_typesNone (static metadata)None
create_dashboardEditor or Owner on projectNone
list_dashboardsViewer or higher on projectNone
share_dashboardEditor or Owner on projectPro required
View in web appAuthenticated project collaboratorNone
Delete in web appAuthenticated tenant memberNone
ErrorCauseFix
output-not-foundThe output_key does not exist in the run’s outputs dictCheck the filename your model wrote to /outputs/ and pass the full filename including .json
output-shape-invalidThe output dict exists but is missing required keys or has the wrong typeCompare your data against the schema returned by list_chart_types
model_run_id … not a valid UUIDMalformed run IDCopy the exact run_id from run or list_runs
status failedThe model run did not complete successfullyRe-run the model and wait for success status
Dashboard … not founddashboard_name does not exist in the projectCheck spelling or call list_dashboards to see valid names
Pro subscription requiredFree-tier tenant calling share_dashboardUpgrade to Pro in Settings → Billing
ToolDescription
list_chart_typesDiscover supported charts and their schemas
create_dashboardGenerate and save dashboard HTML from a model run
list_dashboardsList saved dashboards for a project
share_dashboardShare a dashboard with project collaborators via an authenticated link
runExecute a model and produce the outputs dict
list_runsFind completed runs and their run_id values