# Developing In Lightdash

> Use when working with Lightdash YAML files, dbt models with Lightdash metadata, the lightdash CLI (deploy, upload, download, preview, lint, warehouse-catalog, sql, set-warehouse, apps create/preview/validate), or managing charts, dashboards, spaces and access, AI agents, scheduled content, data apps, organization Data App themes, data-app external connections, users, groups, custom roles, metrics, and dimensions as code

- Skill: `dlt-hub/developing-in-lightdash` (Agent Skill, multi-file: 28 files)
- Install (CLI): `npx skillmds@latest add dlt-hub/developing-in-lightdash`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dlt-hub/developing-in-lightdash/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: dlt-hub (https://skillmd.com/u/dlt-hub)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dlt-hub/developing-in-lightdash

---


# Developing in Lightdash

Build and deploy Lightdash analytics projects. This skill covers the **semantic layer** (metrics, dimensions, joins) and **content** (charts, dashboards).

## When to Use

- Working with Lightdash YAML files (charts, dashboards, models as code)
- Using the `lightdash` CLI (`deploy`, `upload`, `download`, `preview`, `lint`, `warehouse-catalog`, `sql`)
- Defining metrics, dimensions, joins, or tables in dbt or pure Lightdash projects
- Creating or editing charts and dashboards as code
- Downloading, uploading, or locally developing data apps (enterprise)
- Creating, editing, migrating, downloading, or uploading organization Data App themes

**Don't use for:** Developing the Lightdash application itself (use the codebase CLAUDE.md), general dbt work without Lightdash metadata, or raw SQL unrelated to Lightdash models.

## What You Can Do

| Task | Commands | References |
|------|----------|------------|
| Create a pure Lightdash project from warehouse metadata | Use Lightdash or an already-authenticated warehouse CLI to inspect catalog metadata and aggregate profiles | [Creating from a Warehouse Catalog](./resources/creating-from-warehouse-catalog.md) |
| Discover warehouse tables and fields | `lightdash warehouse-catalog --json` | [CLI Reference](./resources/cli-reference.md) |
| Explore data warehouse values | `lightdash sql` to execute raw sql, read .csv results | [CLI Reference](./resources/cli-reference.md) |
| Define metrics & dimensions | Edit dbt YAML or Lightdash YAML | [Metrics](./resources/metrics-reference.md), [Dimensions](./resources/dimensions-reference.md) |
| Create charts | `lightdash download`, edit YAML, `lightdash upload` | [Chart Types](#chart-types) |
| Add period comparisons | Add PoP additional metrics to chart YAML | [Period over Period](./resources/period-over-period-reference.md) |
| Build dashboards | `lightdash download`, edit YAML, `lightdash upload` | [Dashboard Reference](./resources/dashboard-reference.md) |
| Manage content as code across project and organization resources | `lightdash download`, `lightdash upload` | [Content as Code](./resources/content-as-code-reference.md) |
| Manage data apps as code (enterprise) | `lightdash download --apps <ref>` (one app) or `--include-apps` (all), edit bundle, `lightdash upload --apps <ref>`; local dev via `lightdash apps create/preview/validate` | [Data Apps](#working-with-data-apps-enterprise), [Content as Code](./resources/content-as-code-reference.md) |
| Manage organization Data App themes as code | `lightdash download --organization`, edit `themes/<slug>/`, `lightdash upload --organization` | [Data App Themes](./resources/data-app-themes-reference.md) |
| Manage data-app external connections (enterprise) | `lightdash download --include-external-connections`, edit YAML, `lightdash upload` | [Content as Code](./resources/content-as-code-reference.md) |
| Lint yaml files | `lightdash lint` | [CLI Reference](./resources/cli-reference.md) |
| Set warehouse connection | `lightdash set-warehouse` from profiles.yml | [CLI Reference](./resources/cli-reference.md) |
| Deploy changes | `lightdash deploy` (semantic layer), `lightdash upload` (content) | [CLI Reference](./resources/cli-reference.md) |
| Test changes | `lightdash preview` | [Workflows](./resources/workflows-reference.md) |

## Common Mistakes

| Mistake | Consequence | Prevention |
|---------|-------------|------------|
| **Guessing filter values** | Case mismatches (`'Payment'` vs `'payment'`) cause charts to silently return no data | Always run `lightdash sql "SELECT DISTINCT column FROM table LIMIT 50" -o values.csv` and use exact values |
| **Not updating dashboard tiles after renaming a chart** | Dashboard tile still shows old title — `title` and `chartName` are independent overrides that do NOT auto-update | Download the dashboard, find tiles with matching `chartSlug`, update `title` and `chartName` to match |
| **Including unused dimensions in metricQuery** | "Results may be incorrect" warning — extra dimensions change SQL grouping and produce wrong numbers | Every dimension in `metricQuery.dimensions` must appear in the chart config. For cartesian: `layout.xField`, `layout.yField`, or `pivotConfig.columns` |
| **Unsorted YAML keys** | `lightdash upload` warns "unsorted YAML keys" and diffs become noisy | Always sort keys alphabetically at every nesting level — the CLI writes with `sortKeys: true` |
| **Deploying to wrong project** | Overwrites production content | Always run `lightdash config get-project` before deploying |
| **Missing `contentType` field** | Content type can't be determined without relying on directory structure | Always include `contentType: chart`, `contentType: dashboard`, or `contentType: sql_chart` at the top level |
| **Adding `--include-apps` to an `--apps <ref>` selection** | `--include-apps` always requests ALL project apps (capped at 50), so the command downloads every app plus the ref — not just the one app | `--apps <ref>` alone downloads/uploads only that app (by slug, app URL, or UUID). Use `--include-apps` only when you want every app |
| **Editing a data app without reading its bundled skills** | App code violates the SDK-only data access and dependency boundaries (direct `fetch`, `pnpm add`, vendored libraries) and the upload rejects or the app breaks when deployed | Every app bundle ships `.claude/skills/developing-data-apps-locally` and `.claude/skills/lightdash-data-app` — read them before editing files in an app folder (see [Data Apps](#working-with-data-apps-enterprise)) |
| **Inventing a theme-only CLI command or treating a missing folder as deletion** | The command does not exist, or a supposedly deleted remote theme returns on the next download | Use organization download/upload, and read [Data App Themes](./resources/data-app-themes-reference.md) before changing `themes/` |

## Before You Start

When a task uses `lightdash download` or `lightdash upload`, especially for bulk edits, spaces and access, scheduled content, AI agents, data apps, organization themes, external connections, users, groups, or custom roles, **read and follow [Content as Code](./resources/content-as-code-reference.md) first**. Project and organization content require separate commands, and a default download is not a complete snapshot.

For any task that creates, edits, migrates, downloads, uploads, or tests an organization Data App theme, **always read and follow [Data App Themes](./resources/data-app-themes-reference.md) before touching `themes/`**. Theme packages are strict multi-file resources, organization upload has no theme-only mode, and `lightdash lint` does not validate them.

### Check Your Target Project

**Always verify which project you're deploying to.** Deploying to the wrong project can overwrite production content.

```bash
lightdash config get-project        # Show current project
lightdash config list-projects      # List available projects
lightdash config set-project --name "My Project"  # Switch project
```

### Detect Your Project Type

**The YAML syntax differs significantly between project types.**

| Type | Detection | Key Difference |
|------|-----------|----------------|
| **dbt Project** | Has `dbt_project.yml` | Metadata nested under `meta:` |
| **dbt Fusion / dbt 1.10+** | Has `dbt_project.yml`, uses dbt Fusion or dbt >= 1.10 | Metadata nested under `config: meta:` |
| **Pure Lightdash** | Has `lightdash.config.yml`, no dbt | Top-level properties |

```bash
ls dbt_project.yml 2>/dev/null && echo "dbt project" || echo "Not dbt"
ls lightdash.config.yml 2>/dev/null && echo "Pure Lightdash" || echo "Not pure Lightdash"
```

> **dbt Fusion / dbt 1.10+:** Lightdash metadata must be nested under `config: meta:` instead of `meta:`. The properties are identical — only the nesting changes. Example:
> ```yaml
> models:
>   - name: orders
>     config:
>       meta:
>         metrics:
>           total_revenue:
>             type: sum
>             sql: "${TABLE}.amount"
> ```

### Syntax Comparison

**dbt YAML** (metadata under `meta:`):
```yaml
models:
  - name: orders
    meta:
      metrics:
        total_revenue:
          type: sum
          sql: "${TABLE}.amount"
    columns:
      - name: status
        meta:
          dimension:
            type: string
```

**Pure Lightdash YAML** (top-level):
```yaml
type: model
name: orders
sql_from: 'DB.SCHEMA.ORDERS'

metrics:
  total_revenue:
    type: sum
    sql: ${TABLE}.amount

dimensions:
  - name: status
    sql: ${TABLE}.STATUS
    type: string
```

## Setting Up Warehouse Connection

If the project needs a different warehouse connection (e.g., switching from Postgres to BigQuery), update it from your profiles.yml:

```bash
lightdash set-warehouse --project-dir ./dbt --profiles-dir ./profiles --assume-yes
```

This reads credentials from profiles.yml, updates the warehouse connection on the currently selected project, and triggers a recompile. Run this before `lightdash deploy`.

To target a specific project:

```bash
lightdash set-warehouse --project-dir ./dbt --profiles-dir ./profiles --project <uuid> --assume-yes
```

## Core Workflows

### Verify Filter Values Before Using Them

**CRITICAL**: Never guess filter values. Case mismatches (e.g., `'Payment'` vs `'payment'`) cause charts to silently return no data.

Filters are case-sensitive by default. The `case_sensitive` key can override this in order of priority:

- Dimension metadata
- Model/explore metadata
- `lightdash.config.yml` `defaults.case_sensitive`

**Before writing any string filter**, query actual values from the warehouse:

```bash
lightdash sql "SELECT DISTINCT category FROM payments LIMIT 50" -o category_values.csv
```

Read the CSV and use the **exact values** in your filter YAML. This applies to all `equals`/`notEquals` filters with string values — in charts and dashboards.

### Editing Metrics & Dimensions

1. **Find the model YAML file** (dbt: `models/*.yml`, pure Lightdash: `lightdash/models/*.yml`)
2. **Edit metrics/dimensions** using the appropriate syntax for your project type
3. **Validate**: `lightdash lint` (pure Lightdash) or `dbt compile` (dbt projects)
4. **Deploy**: `lightdash deploy`

See [Metrics Reference](./resources/metrics-reference.md) and [Dimensions Reference](./resources/dimensions-reference.md) for configuration options.

### Creating a Pure Lightdash Project from a Warehouse Catalog

When the prepared project has no usable dbt project and the task is to bootstrap a semantic layer from warehouse metadata, **always read and follow [Creating from a Warehouse Catalog](./resources/creating-from-warehouse-catalog.md) before inspecting data or writing YAML**. This applies whether warehouse access comes from the selected Lightdash project or an already-authenticated warehouse CLI such as Snowflake CLI or `bq`. Do not use that workflow when an existing dbt semantic layer can be extended.

### Editing Charts

1. **Download**: `lightdash download --charts chart-slug`
2. **Edit** the YAML file in `lightdash/` directory
3. **Verify filter values**: If you added or changed filters, use `lightdash sql` to check actual column values (see [Common Mistakes](#common-mistakes))
4. **Update dashboard tiles**: If you changed the chart's name or purpose, download any dashboards that reference it and update their tile `title` and `chartName` properties to match (see [Common Mistakes](#common-mistakes))
5. **Lint**: `lightdash lint` to validate before uploading
6. **Upload**: `lightdash upload --charts chart-slug` (and any modified dashboards)

**Dashboard tiles have their own titles.** A `saved_chart` tile's `title` and `chartName` properties are independent overrides — they do NOT auto-update when you rename the chart. If you change a chart from "Total Revenue" to "Gross Profit" but don't update the dashboard tile, the dashboard will still display "Total Revenue". Always download the dashboard, find tiles with matching `chartSlug`, and update their `title` and `chartName` to match.

```yaml
# Dashboard tile — title and chartName must be updated manually when chart changes
tiles:
  - type: saved_chart
    properties:
      chartSlug: total-revenue-kpi
      title: "Gross Profit"        # ← Update this when chart name/purpose changes
      chartName: "Gross Profit"    # ← Update this too
```

### Editing Dashboards

1. **Download**: `lightdash download --dashboards dashboard-slug`
2. **Edit** the YAML file in `lightdash/` directory
3. **Verify filter values**: If you added or changed filters, use `lightdash sql` to check actual column values (see [Common Mistakes](#common-mistakes))
4. **Lint**: `lightdash lint` to validate before uploading
5. **Upload**: `lightdash upload --dashboards dashboard-slug`

### Working with Data Apps (Enterprise)

Data apps are multi-file React bundles under `apps/<app-folder>/` with a `lightdash-app.yml` manifest — not single YAML files. Full flag semantics and manifest details: [Content as Code](./resources/content-as-code-reference.md).

**Download one app** — `--apps <ref>` alone is the complete command (ref = slug, app URL, or UUID; also finds apps not added to any space):

```bash
lightdash download --apps revenue-explorer --path ./lightdash
```

Never add `--include-apps` to "scope" the download — it always requests ALL project apps (see [Common Mistakes](#common-mistakes)).

**Download all apps**: `lightdash download --include-apps` (capped at 50; raise with `--apps-limit <n>`). Add `--apps-only` to skip charts, dashboards, and spaces.

**Upload**:

```bash
lightdash upload --apps revenue-explorer   # one app (slug = folder name, URL, or UUID)
lightdash upload --include-apps            # every app folder on disk
```

- `--app-space <spaceRef>` — space (slug or UUID) for apps this upload **creates**; existing apps keep their space.
- `--create-new` — create a fresh app (new slug) instead of updating the app referenced in `lightdash-app.yml`.
- `--allow-custom-dependencies` — required for non-interactive uploads of apps that declare custom npm dependencies.

**Develop locally** with the `lightdash apps` subcommand group:

```bash
lightdash apps create "Revenue Explorer"   # scaffold a new app under ./lightdash/apps/
lightdash apps preview                     # run the app locally against your real Lightdash instance, authenticated as you
lightdash apps validate                    # check source, manifest, dependencies, and semantic-layer references
```

**Every created or downloaded app bundle ships its own skills** in `.claude/skills/` inside the app folder:

- `developing-data-apps-locally` — the edit → validate → upload loop, local preview, SDK-only data access, and dependency boundaries
- `lightdash-data-app` — the `@lightdash/query-sdk` reference for the app's source code

When editing files inside an app folder, **read those bundled skills first**. They are version-matched to the app and authoritative for local development — this skill only covers moving apps between disk and Lightdash.

### Working with Organization Data App Themes

Organization Data App themes are multi-file packages under `themes/<slug>/` and participate automatically in `lightdash download --organization` and `lightdash upload --organization`. They do not have a standalone command group or theme-specific selectors.

Before creating, editing, migrating, synchronizing, or testing a theme, **read and follow [Data App Themes](./resources/data-app-themes-reference.md)** for the manifest contract, asset rules, synchronization behavior, and generation boundaries.

### Creating New Content

Charts and dashboards are typically created in the UI first, then managed as code:

1. Create in UI
2. `lightdash download` to pull as YAML
3. Edit and version control
4. `lightdash lint` to validate before uploading
5. `lightdash upload` to sync changes

### Testing with Preview

For larger changes, test in isolation:

```bash
lightdash preview --name "my-feature"
# Make changes and iterate
lightdash stop-preview --name "my-feature"
```

## CLI Quick Reference

| Command | Purpose |
|---------|---------|
| `lightdash deploy` | Sync semantic layer (metrics, dimensions) |
| `lightdash upload` | Upload charts/dashboards |
| `lightdash download` | Download charts/dashboards as YAML |
| `lightdash lint` | Validate YAML locally |
| `lightdash preview` | Create temporary test project |
| `lightdash warehouse-catalog --json` | Discover raw warehouse tables |
| `lightdash sql "..." -o file.csv` | Run SQL queries against warehouse |
| `lightdash run-chart -p chart.yml` | Execute chart YAML query against warehouse |
| `lightdash apps create <name>` | Scaffold a new data app locally (enterprise) |
| `lightdash apps preview` | Run a data app locally against your Lightdash instance |
| `lightdash apps validate` | Validate data app source, manifest, and semantic references |

See [CLI Reference](./resources/cli-reference.md) for full command documentation.

## Semantic Layer

The semantic layer defines your data model. See individual references for full configuration:

- [Tables Reference](./resources/tables-reference.md) — queryable entities, labels, joins
- [Metrics Reference](./resources/metrics-reference.md) — aggregated calculations (`count`, `sum`, `average`, `min`, `max`, `number`, etc.)
- [Dimensions Reference](./resources/dimensions-reference.md) — attributes for grouping/filtering (`string`, `number`, `boolean`, `date`, `timestamp`)
- [Joins Reference](./resources/joins-reference.md) — cross-table relationships
- [User Attributes Reference](./resources/user-attributes-reference.md) — SQL variables, row-level security, access control

## Chart Types

All charts share a common base structure:

```yaml
chartConfig:
  config: {}        # Type-specific — see individual references
  type: <type>
contentType: chart              # Required: chart, dashboard, or sql_chart
dashboardSlug: my-dashboard  # Optional: scopes chart to dashboard (won't appear in space)
metricQuery:
  dimensions:
    - my_explore_category
  exploreName: my_explore     # Required: which explore to query
  filters: {}
  limit: 500
  metrics:
    - my_explore_total_sales
  sorts: []
name: "Chart Name"
slug: unique-chart-slug
spaceSlug: target-space
tableConfig:
  columnOrder: []
tableName: my_explore           # Required: top-level explore/table name
version: 1
```

**Key ordering:** All YAML keys must be sorted alphabetically at every nesting level. The CLI writes files with `sortKeys: true` and warns on upload if keys are unsorted. When writing or editing YAML by hand, keep keys in alphabetical order to avoid warnings and noisy diffs.

**Chart scoping:** Use `spaceSlug` only for shared charts. Add `dashboardSlug` to scope a chart to a specific dashboard (it won't appear in the space).

**Nested spaces:** Spaces can be nested. In YAML, `spaceSlug` uses `parent/child` syntax to address a sub-space — the `/` denotes hierarchy. Examples:

```yaml
spaceSlug: sales              # Top-level space "sales"
spaceSlug: sales/maps         # Sub-space "maps" inside "sales"
spaceSlug: sales/eu/forecasts # Deeper nesting works the same way
```

Each path segment must be the slug of an existing (or to-be-created) space at that level. A bare slug like `sales-maps` is a flat top-level space, NOT a sub-space — the slash is the only thing that creates the hierarchy.

### Choosing the Right Chart Type

| Data Pattern | Recommended Chart | Why |
|--------------|-------------------|-----|
| Trends over time | Line or area (`cartesian`) | Shows continuous change with time on X-axis |
| Category comparisons | Bar (`cartesian`) | Easy visual comparison between discrete categories |
| Part-of-whole relationships | `pie` or `treemap` | Shows proportions summing to 100% |
| Single KPI metric | `big_number` | Focuses attention on one important value |
| Conversion stages | `funnel` | Visualizes drop-off between sequential steps |
| Progress toward target | `gauge` | Shows current value relative to goal |
| Geographic data | `map` | Plots data points or regions on a map |
| Flow between categories | `sankey` | Shows how values move from source to target nodes |
| Detailed records | `table` | Displays raw data with sorting and formatting |
| Advanced custom needs | `custom` | Full Vega-Lite spec for custom visualizations |

| Type | Use Case | Reference |
|------|----------|-----------|
| `cartesian` | Bar, line, area, scatter | [Cartesian](./resources/cartesian-chart-reference.md) |
| `pie` | Parts of whole | [Pie](./resources/pie-chart-reference.md) |
| `table` | Data tables | [Table](./resources/table-chart-reference.md) |
| `big_number` | KPIs | [Big Number](./resources/big-number-chart-reference.md) |
| `funnel` | Conversion funnels | [Funnel](./resources/funnel-chart-reference.md) |
| `gauge` | Progress indicators | [Gauge](./resources/gauge-chart-reference.md) |
| `treemap` | Hierarchical data | [Treemap](./resources/treemap-chart-reference.md) |
| `map` | Geographic data | [Map](./resources/map-chart-reference.md) |
| `sankey` | Flow diagrams | [Sankey](./resources/sankey-chart-reference.md) |
| `custom` | Vega-Lite | [Custom Viz](./resources/custom-viz-reference.md) |

## Dashboards

Dashboards arrange charts and content in a grid layout. See [Dashboard Reference](./resources/dashboard-reference.md) for YAML structure, tile types, tabs, and filters.

## Exploring the Warehouse

Use `lightdash sql` to explore data when building models:

```bash
# Preview table structure
lightdash sql "SELECT * FROM orders LIMIT 5" -o preview.csv

# Check distinct values for a dimension
lightdash sql "SELECT DISTINCT status FROM orders" -o statuses.csv

# Test metric calculations
lightdash sql "SELECT SUM(amount) FROM orders" -o test.csv
```

## Workflow Patterns

| Pattern | When to Use |
|---------|-------------|
| **Direct** (`deploy` + `upload`) | Solo dev, rapid iteration |
| **Preview-First** | Team, complex changes |
| **CI/CD** | Automated on merge |

See [Workflows Reference](./resources/workflows-reference.md) for detailed examples and CI/CD configurations.

## Resources

### Semantic Layer
- [Creating from a Warehouse Catalog](./resources/creating-from-warehouse-catalog.md)
- [Dimensions Reference](./resources/dimensions-reference.md)
- [Metrics Reference](./resources/metrics-reference.md)
- [Tables Reference](./resources/tables-reference.md)
- [Joins Reference](./resources/joins-reference.md)
- [User Attributes Reference](./resources/user-attributes-reference.md)

### Charts
- [Cartesian Chart Reference](./resources/cartesian-chart-reference.md) - Bar, line, area, scatter
- [Pie Chart Reference](./resources/pie-chart-reference.md)
- [Table Chart Reference](./resources/table-chart-reference.md)
- [Big Number Reference](./resources/big-number-chart-reference.md)
- [Funnel Chart Reference](./resources/funnel-chart-reference.md)
- [Gauge Chart Reference](./resources/gauge-chart-reference.md)
- [Treemap Chart Reference](./resources/treemap-chart-reference.md)
- [Map Chart Reference](./resources/map-chart-reference.md)
- [Sankey Chart Reference](./resources/sankey-chart-reference.md)
- [Custom Viz Reference](./resources/custom-viz-reference.md)
- [Period over Period Reference](./resources/period-over-period-reference.md) - PoP comparisons (YoY, MoM, etc.)

### Dashboards & Workflows
- [Dashboard Reference](./resources/dashboard-reference.md)
- [Dashboard Best Practices](./resources/dashboard-best-practices.md)
- [Data App Themes Reference](./resources/data-app-themes-reference.md)
- [Content as Code Reference](./resources/content-as-code-reference.md)
- [CLI Reference](./resources/cli-reference.md)
- [Workflows Reference](./resources/workflows-reference.md)

### External
- [Lightdash Docs](https://docs.lightdash.com)

