Getting Started Tutorial¶
Step-by-step tutorial for building your first Dataface dashboard from SQL.
Prerequisites Check¶
Before starting, ensure you have:
- ✅ Dataface installed (
dft --version— see Installation) - ✅ A database Dataface can query — Postgres, Snowflake, BigQuery, DuckDB, SQLite, or a local CSV/Parquet file
You do not need dbt or a Semantic Layer to build dashboards. Most projects start with plain SQL. If you already run dbt and want governed metrics, the MetricFlow integration is an optional upgrade you can adopt later.
Step 1: Set Up Project Structure¶
Dataface dashboards ("faces") live in a faces/ directory. A minimal project
is just that directory plus a dataface.yml that names your data source:
my-project/
├── dataface.yml # Names your data source(s)
├── faces/ # Your dashboards here
│ └── my_first_dashboard.yml
└── assets/ # Optional: images, CSV data files
├── images/
└── data/
Point dataface.yml at a database. A local DuckDB file needs no credentials,
which makes it the quickest way to start:
# dataface.yml sources: analytics: type: duckdb path: ./data/analytics.duckdb
See Sources for Postgres, Snowflake, BigQuery, and dbt profile connections.
Step 2: Create a Dashboard File¶
Create faces/my_first_dashboard.yml with a title and the source it reads from:
title: "My First Dashboard" source: analytics
The face-level source: applies to every query in the dashboard, so you don't
repeat it on each one.
Step 3: Define a Query¶
Add a SQL query that returns the columns you want to chart:
title: "My First Dashboard" source: analytics queries: sales: sql: | SELECT date_trunc('month', ordered_at) AS month, SUM(amount) AS revenue, COUNT(*) AS orders FROM orders GROUP BY 1 ORDER BY 1
The query owns the data: its grain, aggregation, and ordering. Each query has a
name (sales) and returns named columns (month, revenue, orders) that
charts bind to.
Step 4: Create a Chart¶
Add a chart that maps query columns to visual channels:
title: "My First Dashboard" source: analytics queries: sales: sql: | SELECT date_trunc('month', ordered_at) AS month, SUM(amount) AS revenue, COUNT(*) AS orders FROM orders GROUP BY 1 ORDER BY 1 charts: revenue_chart: title: "Revenue by Month" query: sales type: bar x: month y: revenue
The chart doesn't aggregate or infer anything — the query already did that. The
chart only decides that month goes on the x-axis and revenue on the y-axis.
Step 5: Organize with Layouts¶
Layouts arrange your charts. Use rows to stack, cols to place side by side,
or grid for precise columns:
rows: - title: "Sales Overview" cols: - revenue_chart - orders_chart
Step 6: Validate and Preview¶
Validate the dashboard:
Fix any errors it reports, then start a live preview:
Open the URL dft serve prints on startup to see your dashboard. It re-renders
as you edit the YAML.
Step 7: Add Variables¶
Variables are the controls readers use to filter a dashboard. Wire one into the
query with the filter() helper — it writes the SQL predicate for the selected
value, or a no-op when nothing is selected:
title: "My First Dashboard" source: analytics variables: region: input: select options: static: ["North", "South", "East", "West"] # No default: starts on All regions queries: sales: sql: | SELECT date_trunc('month', ordered_at) AS month, SUM(amount) AS revenue, COUNT(*) AS orders FROM orders WHERE {{ filter('region', region) }} GROUP BY 1 ORDER BY 1 charts: revenue_chart: title: "Revenue by Month" query: sales type: bar x: month y: revenue rows: - title: "Sales Overview" cols: - revenue_chart
Now the region selector filters the chart. A variable never filters data on its own — you always wire it into a query explicitly.
Step 8: Add More Charts¶
Add another chart and place both in a grid:
charts: revenue_chart: title: "Revenue by Month" query: sales type: bar x: month y: revenue orders_chart: title: "Orders by Month" query: sales type: line x: month y: orders rows: - title: "Sales Overview" grid: columns: 24 items: - item: revenue_chart width: 12 - item: orders_chart width: 12
Complete Example¶
Here's the full dashboard, with both charts split by region:
title: "My First Dashboard" source: analytics variables: region: input: select options: static: ["North", "South", "East", "West"] # No default: starts on All regions queries: sales: sql: | SELECT date_trunc('month', ordered_at) AS month, region, SUM(amount) AS revenue, COUNT(*) AS orders FROM orders WHERE {{ filter('region', region) }} GROUP BY 1, 2 ORDER BY 1 charts: revenue_chart: title: "Revenue by Month" query: sales type: bar x: month y: revenue color: region orders_chart: title: "Orders by Month" query: sales type: line x: month y: orders color: region rows: - title: "Sales Overview" grid: columns: 24 items: - item: revenue_chart width: 12 - item: orders_chart width: 12
Next Steps¶
Now that you've built your first dashboard:
- Read the Queries Guide — SQL, values, files, HTTP, dbt models, and MetricFlow
- Read the Charts Guide — explore chart types and options
- Read the Variables Guide — add more interactive filters
- See Examples — explore complete dashboards
- Best Practices — dashboard design best practices
Common Questions¶
How do I know which tables and columns are available?¶
Use dft query against INFORMATION_SCHEMA to browse your source's tables
and columns without leaving the terminal:
Can I use dbt metrics instead of SQL?¶
Yes. If your dbt project has a Semantic Layer, a query can use
metrics:/dimensions: instead of sql:. See
MetricFlow.
Can I use multiple queries?¶
Yes — define multiple queries and reference them from different charts.
How do I add more rows?¶
Add more items to the rows array. Each row can have its own cols or grid.
Can I customize colors and styling?¶
Yes. See the Styling Guide for themes and styling options.
Related¶
- Installation Guide — installation and setup
- CLI Reference — complete CLI command reference
- Troubleshooting Guide — common issues and solutions
- Best Practices Guide — dashboard design best practices
- Queries Guide — query reference
- Charts Guide — chart reference
- Variables Guide — variables reference