> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getnao.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate your BI to nao

> Move your Metabase dashboards and Tableau workbooks into nao stories

nao can migrate your existing BI content into [stories](/nao-agent/chat/bi/stories), so you move off your dashboard tool without rebuilding every report by hand. Two agent skills cover it today:

* **`migrate-metabase`** - turn a Metabase dashboard, collection, or saved question into nao charts and stories.
* **`migrate-tableau-workbook`** - turn a published Tableau workbook, dashboard, or worksheet into a nao story.

<Info>
  A migration produces a **snapshot**, not a live connection to your BI tool. Once the content is a nao story you can turn on [live mode](/nao-agent/chat/capabilities/stories#live-stories) so it refreshes from your warehouse on a schedule. The result is close to the original but not pixel-perfect.
</Info>

## How it works

Each migration is an agent skill backed by the nao-core CLI. In chat, trigger it with a `/` shortcut (`/migrate-metabase`, `/migrate-tableau-workbook`) or a natural request such as *"migrate my Metabase sales dashboard into a story"*. Under the hood the agent:

1. Runs a `nao migrate ...` command that exports the dashboard or workbook definition (and, for Tableau, a CSV and image of each worksheet) to a temporary file.
2. Maps the source data to one of your configured nao [databases](/nao-agent/context-builder/databases) and rebuilds each query against it.
3. Composes the result as nao charts in the thread, or assembles a [story](/nao-agent/chat/capabilities/stories) with the layout, tabs, text, and filters preserved.
4. Ends with a summary of anything it could not carry across.

## Prerequisites

* The **nao-core CLI**, run from your project directory (the one with `nao_config.yaml`).
* A nao **database** configured on the same source data your BI tool reads. Migrated queries run against your warehouse through nao, not against the BI tool's cached results, so the agent needs a matching connection.
* **Credentials** for the BI tool, stored in `nao_config.yaml`. Use the `configure` commands below rather than pasting secrets into chat.

<Warning>
  Credentials live in `nao_config.yaml` as plain text. Keep that file out of version control and inject the values from environment variables or a secrets manager.
</Warning>

## Metabase

### Connect

Run the interactive setup from your project directory:

```bash theme={null}
nao migrate metabase configure
```

It prompts for your Metabase URL and an API key and writes them to `nao_config.yaml`:

```yaml theme={null}
metabase:
  url: https://metabase.your-company.com
  api_key: "{{ env('METABASE_API_KEY') }}"
```

A `401` or `403` during a migration means the credentials are stale - run `configure` again.

### Migrate

Ask the agent to migrate, or run the skill. It picks a delivery based on what you point it at:

* A **dashboard** becomes one story, keeping its layout, tabs, text cards, and filters.
* A single **saved question** becomes one chart.
* A **collection** becomes one story per dashboard it contains.

The skill drives these commands under the hood (identify sources by their numeric Metabase **ID or URL**, not by name):

```bash theme={null}
nao migrate metabase dashboard '<id-or-url>' --json
nao migrate metabase question '<id-or-url>' --json
nao migrate metabase collection '<id-or-url>' --recursive --json
```

### What carries across

Dashboard visualizations, grid widths, tabs, text cards, and dashboard filters (when nao has a matching filter type) are converted. Chart types are mapped to their nao equivalents - scalars to KPI cards, line/bar/area/pie/combo/row charts to the matching nao chart, tables to tables, and maps to nao maps.

Known limits:

* Not pixel-perfect.
* Saved questions are not executed unless you opt in (`--allow-query-execution`); the migration works from each card's compiled SQL.
* Questions with bound SQL parameters are skipped - nao's SQL execution does not take them.
* Only read-only `SELECT` SQL is migrated; multi-statement, DDL, or data-changing SQL is rejected.
* Deleted or inaccessible cards, and filters with no matching nao type, are skipped and reported rather than silently dropped.

## Tableau

### Connect

Run the interactive setup from your project directory:

```bash theme={null}
nao migrate tableau configure
```

It prompts for your server, site, a Personal Access Token (PAT), and the REST API version, and writes them to `nao_config.yaml`:

```yaml theme={null}
tableau:
  server: https://your-tableau-server.com
  site_name: ""            # optional, blank for the default site
  pat_name: nao-migration
  pat_value: "{{ env('TABLEAU_PAT') }}"
  api_version: "3.21"      # optional, defaults to 3.21
```

<Note>
  The workbook must be **published** to Tableau Cloud or Tableau Server. Local `.twb` / `.twbx` files are not supported, because nao needs the per-worksheet data and images that only a published workbook exposes over the REST API.
</Note>

### Migrate

Trigger the skill or ask the agent in plain English. It maps the source like this:

* A whole **workbook** becomes one story: each dashboard is a tab, and each worksheet that is not on a dashboard becomes its own tab.
* A single **dashboard** becomes a story tab.
* A single **worksheet or view** becomes one chart in the thread.

Under the hood it runs:

```bash theme={null}
nao migrate tableau "<workbook-name>" --output <migration.json>
```

Add `--project "<project-name>"` to disambiguate workbooks that share a name, or `--dashboard "<dashboard-name>"` to scope the migration to one dashboard.

### What carries across

Workbook composition (dashboards to tabs, worksheets to charts), worksheet visualization metadata, layout rows (to nao grids), and visible categorical dashboard filters (to story filters with templated SQL) are converted. The agent reads the exported worksheet image to confirm each chart type.

Known limits:

* A snapshot, not a live sync, and not pixel-identical.
* Tableau story points and actions (filter, highlight, URL, navigation) are not migrated.
* Calculated fields, context filters, LOD expressions, sets, groups, and bins are only reproduced when they are verifiable from the exported data and images, not parsed from the workbook XML.
* Free-form or range parameters are not reproduced when nao has no native control for them; all categorical controls become multi-select filters.
* Permissions, subscriptions, and alerts are not migrated. Worksheets whose assets fail to export are skipped and reported.

## After migrating

The output is an ordinary nao story. From there you can:

* Turn on [live mode](/nao-agent/chat/capabilities/stories#live-stories) so it refreshes on a schedule instead of staying a snapshot.
* [Share](/nao-agent/chat/capabilities/stories#sharing-a-story) it with your project or a user group, and [certify](/nao-agent/chat/capabilities/stories#certified-stories) it once reviewed.
* Edit it like any other story - rearrange blocks, fix a query, or add [filters](/nao-agent/chat/capabilities/stories#filters).

See [Stories](/nao-agent/chat/bi/stories) for how stories replace a BI dashboard.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.