Dashboards
Create custom data visualization dashboards with AI-assisted chart creation, drag-and-drop layouts, and public sharing.
Production Ready - Full dashboard system with chart editor, 12+ chart types, workspace sharing, and public links
Overview
QRY Dashboards provide a powerful way to create custom data visualizations. Build interactive dashboards with multiple chart types, tables, KPIs, and share them with your team or publicly.
Key Capabilities:
- Drag-Drop Layout - Resize and reposition tiles freely on a 12-column grid
- 15+ Chart Types - Bar, line, pie, heatmap, sankey, treemap, sunburst, boxplot, candlestick, and more
- Interactive Filters - Add filter controls that dynamically update all tiles
- Drill-Down & Cross-Filter - Click a category to filter every tile or descend into a hierarchy
- Click-to-Detail - Open the raw rows behind any chart point or KPI in a modal
- Export - Download tile data as CSV or Excel (XLSX)
- AI Analytics - "Explain this" tile insights, dashboard Q&A, anomaly detection, and forecasting
- AI SQL Assist - Section-specific AI writers for click-to-detail, period comparison, drill-down hierarchy, and cross-filter audit
- Period Comparison - Built-in placeholders for previous-period KPIs without custom SQL
- AI Integration - Add charts directly from AI conversations
- Public Sharing - Generate unique URLs for external viewers
- Auto-Refresh - Configure refresh intervals from 30 seconds to 1 hour
- Workspace Integration - Share dashboards with team members
Quick Start
Creating Your First Dashboard
- Navigate to Dashboards from the left navigation rail
- Click + New Dashboard
- Enter a name and optionally assign to a workspace
- Click Create Dashboard to open the editor
Adding Tiles
- Click + Add Tile in the toolbar
- Choose a tile type: Chart, KPI, Table, or Text
- Configure the datasource and write your SQL query
- Map chart fields (X-axis, Y-axis) and customize appearance
- Click Add Tile to place it on the dashboard
Sharing Dashboards
- Click the Share button in the toolbar
- Toggle "Make Public" to generate a shareable link
- Anyone with the link can view the dashboard (read-only)
Tile Types
| Type | Description | Use Case |
|---|---|---|
| Chart | ECharts visualization with 12+ chart types | Data trends, comparisons, distributions |
| KPI | Single metric with optional comparison | Key performance indicators, targets |
| Table | Data table with sorting | Detailed data views, records listing |
| Text | Static HTML/markdown content | Headers, notes, embedded images |
Chart Types
QRY supports a wide variety of chart types powered by ECharts:
Standard Charts
- Bar / Line / Area - Standard charts for time series and comparisons
- Pie / Funnel - Part-to-whole relationships
- Scatter - Correlation analysis
Advanced Visualizations
- Heatmap - Matrix data visualization
- Treemap / Sunburst - Hierarchical data proportions (sunburst is the radial variant)
- Sankey / Chord - Flow and relationship diagrams
- Gauge - Single value with target
- Radar - Multi-dimensional comparisons
- Boxplot - Distribution + outliers (Tukey 5-number summary)
- Candlestick - OHLC for finance / time-series ranges
Chart Field Mapping
Different chart types require different field configurations:
| Chart Type | Required Fields |
|---|---|
| Bar/Line/Area | X-axis field, Y-axis field |
| Pie/Funnel | Name field, Value field |
| Heatmap | X field, Y field, Value field |
| Sankey/Chord | Source field, Target field, Value field |
| Treemap | Name field, Value field, Category field |
| Sunburst | Path fields (parent → child), Value field |
| Boxplot | Category field, Value field |
| Candlestick | Date field, Open / High / Low / Close fields |
| Gauge | Value field |
Dashboard Editor
Layout Grid
The editor uses a 12-column grid system:
- Drag tiles to reposition them anywhere
- Resize using the handle in the bottom-right corner
- Tiles snap to grid positions automatically
- Layout saves automatically as you work
Toolbar Actions
| Button | Action |
|---|---|
| + Add Tile | Open tile wizard |
| Refresh | Re-execute all queries |
| Preview | Toggle preview mode (hide grid) |
| Ask | Open the dashboard Q&A panel |
| Cross-filter | Toggle click-to-filter across all tiles |
| Share | Generate public link |
| Settings | Edit dashboard properties and filters |
Tile Configuration Panel
Click any tile to open the configuration panel:
Dataset Section
- Select datasource
- Choose catalog and schema
- Write or edit SQL query
- Run query to preview results
Visualization Section
- Change chart type
- Edit title
- Configure axis mappings (X, Y, Series)
Display Options
- Show/hide legend
- Stacked bars/areas
- Smooth line curves
- Horizontal orientation
Dashboard Filters
Add interactive filter controls that allow users to dynamically filter data across all tiles.
Filter Types
| Type | Description | Example Use |
|---|---|---|
| Select | Single value dropdown | Status, Category |
| Multi-Select | Multiple values selection | Regions, Products |
| Date Range | Start and end date picker | Report periods |
| Date | Single date picker | Snapshot date |
| Text | Free text input | Search terms, Year |
Adding Filters
- Click Settings in the toolbar
- Go to the Filters tab
- Click + Add Filter
- Configure the filter:
- ID - Unique identifier for SQL placeholders (e.g.,
status,date_range) - Label - Display name shown to users
- Type - Select the filter type
- Options - For Select/Multi-Select: define available options
- Default - Optional default value
- ID - Unique identifier for SQL placeholders (e.g.,
Using Filters in SQL Queries
Reference filters in your tile queries using the ${filterId} placeholder syntax:
-- Simple filter
SELECT * FROM orders
WHERE status = ${status}
-- Multi-select filter (use with IN clause)
SELECT * FROM sales
WHERE region IN (${regions})
-- Date range filter
SELECT * FROM transactions
WHERE date >= ${date_range.start}
AND date <= ${date_range.end}
-- Combining multiple filters
SELECT product, SUM(amount) as total
FROM orders
WHERE status = ${status}
AND region IN (${regions})
AND order_date >= ${period.start}
AND order_date <= ${period.end}
GROUP BY product
Filter Placeholder Reference
| Filter Type | Placeholder Syntax | SQL Output Example |
|---|---|---|
| Select | ${status} | 'active' or 123 (numeric) |
| Multi-Select | ${regions} | 'North', 'South', 'East' |
| Date Range | ${range.start}, ${range.end} | '2024-01-01', '2024-12-31' |
| Date | ${date} | '2024-06-15' |
| Text | ${search} | 'keyword' or 2024 (numeric) |
Filter values that are valid numbers (integers or decimals) are automatically inserted without quotes. String values are properly quoted and escaped for SQL safety.
Date Range Presets
The date range picker includes convenient presets organized in tabs:
Presets Tab:
- Today, Yesterday
- Last 7 / 14 / 30 Days
- Last 90 / 180 / 365 Days (in "More" section)
- Year To Date
- This Week / Month / Quarter / Year
- Previous Week / Month / Quarter / Year
Custom Tab:
- Manual start and end date selection
When a preset is selected, the button displays the preset name (e.g., "Year To Date") instead of the date range.
Filter Behavior
- Auto-refresh: Tiles automatically refresh when filter values change
- Debouncing: Text filters wait 300ms after typing stops before triggering refresh
- Loading indicator: Tiles show a spinner overlay during data refresh
- URL sync: Filter values are reflected in the URL for shareable links
- Defaults: Filters use configured defaults on initial dashboard load
Filter Tips
- Use meaningful IDs - Choose descriptive filter IDs like
date_rangeorproduct_category - Add placeholders in comments - Document available filters in SQL comments for clarity
- Test with Preview - Use the SQL editor's Preview button to test filter substitution
- Consider NULL handling - Unset filters substitute as
NULL
Adding Charts from Conversations
When the AI generates a chart in a conversation, you can add it directly to a dashboard:
- Click the Add to Dashboard button on the chart
- Select an existing dashboard or create a new one
- Enter a title for the tile
- Click Add to Dashboard
Supported Chart Sources
| Source | Storage | Behavior |
|---|---|---|
| SQL Charts | Query stored | Re-executes on refresh (live data) |
| Matplotlib/Seaborn | Image embedded | Static snapshot |
| Plotly | HTML embedded | Interactive (click to view fullscreen) |
Plotly Charts
Plotly charts are displayed as preview cards for security. Click View Chart to open a fullscreen modal with full interactivity (zoom, pan, hover). You can also download the chart as an HTML file.
Public Sharing
Making a Dashboard Public
- Click the Share button in the toolbar
- Toggle "Make Public"
- Link is automatically copied to clipboard
- Share the link with anyone - no login required
How Public Dashboards Work
- No login required to view public dashboards
- Data comes from cached snapshots (not live queries)
- Read-only - viewers cannot edit
- Auto-updates when owner creates new snapshot
A snapshot is automatically created when you make a dashboard public. The snapshot caches query results so public viewers don't need database access.
Revoking Access
- Click Share
- Toggle "Make Private"
- Existing links immediately stop working
Workspace Dashboards
Assigning to a Workspace
- Create a new dashboard or edit an existing one
- Select a workspace from the dropdown
- All workspace members can now view and edit the dashboard
Access Control
| User | View | Edit Tiles | Delete/Share Dashboard |
|---|---|---|---|
| Dashboard Owner | Yes | Yes | Yes |
| Workspace Members | Yes | Yes | No |
| Non-members | No | No | No |
Important: Workspace membership grants dashboard access but does NOT grant access to underlying datasources. RBAC permissions still apply - workspace members must have permission on the datasources to execute tile queries.
Configuring Tiles
KPI Tiles
Display a single metric with rich context:
- Big number that auto-scales to fit the tile (uses container queries — drop a KPI into a tiny column and the number shrinks to match).
- Count-up animation on first render so the value feels live.
- Prefix / Suffix (e.g.,
$,%,M) and decimal control. - Delta chip comparing current vs. previous period — sign-aware colours (green ↑ / red ↓, swap polarity for "lower is better" metrics).
- Sparkline under the number when the query returns a time series — a compact trend view alongside the headline figure.
- Period comparison: pick a
compareField(a second numeric column) and the tile shows current vs. previous side-by-side. Combine with the${filter.prev_start}/${filter.prev_end}placeholders to write the comparison cleanly (see Period Comparison). - "Lower is better" flag — for metrics like error rate or latency, mark this so a negative delta is shown in green.
Table Tiles
Show data in tabular format:
- Sortable columns by clicking headers
- Zebra striping option for readability
- Compact mode for dense data
- Limited to 100 rows displayed
Text Tiles
Add static content:
- Headers and section labels
- Instructions or notes
- Embedded images
- HTML formatting supported
Period Comparison
Most dashboards have a "vs. previous period" need built into them. Qry exposes two placeholders alongside any date range filter so you can write the comparison without hand-rolling DATE_SUB arithmetic per warehouse:
| Placeholder | Value |
|---|---|
${range.start} / ${range.end} | Current period bounds (as picked by the user). |
${range.prev_start} / ${range.prev_end} | Half-open: prev_start ≤ x < prev_end, with prev_end == range.start so the two windows touch but don't overlap. |
SELECT
SUM(CASE WHEN order_date >= ${range.start}
AND order_date < ${range.end}
THEN amount END) AS revenue,
SUM(CASE WHEN order_date >= ${range.prev_start}
AND order_date < ${range.prev_end}
THEN amount END) AS revenue_prev
FROM orders
< on prev_endThe previous window is half-open: prev_end is set to the current period's start. Using BETWEEN or <= against prev_end will double-count the boundary row (it falls in both windows). Always use strict < on prev_end (and ideally on end for the same reason, although the current period's right boundary is inclusive in the picker).
On a KPI tile, set Value field to revenue and Comparison field to revenue_prev — the delta chip appears automatically. The two fields cannot be the same column (the editor warns you and the dropdown filters duplicates).
When the AI Assist writes period-comparison SQL it uses these placeholders by default — it does not insert literal DATE_SUB(..., INTERVAL 30 DAY) because that breaks portability across BigQuery / Snowflake / Postgres / etc.
Interactivity
Tiles can react to user input in three layered ways. When more than one is configured on the same chart, Qry picks the most specific one for each click:
Drill-down → Click-to-detail → Cross-filter.
Drill-Down
Configure a hierarchy of levels (e.g., country → region → store) on a chart tile. Clicking a category descends one level and re-runs the query with the clicked value bound to a placeholder; a breadcrumb appears above the tile so the user can pop back at any level.
- Open the tile config panel → Interactions tab.
- Add drill levels in order from broadest to narrowest. Each level has a label column (what the user sees) and an id column (what gets pushed into the next query).
- Reference the drilled value in the query with
${drill.value}and the drillWHEREclause with${drill.where}— the latter is what Qry generates as the filter chain (e.g.,country = 'ES' AND region = 'Madrid').
SELECT
${drill.label_column} AS label,
SUM(revenue) AS revenue
FROM sales
WHERE 1=1 ${drill.where}
GROUP BY 1
The drill state is per-tile, persisted only in-memory during the session, and reflected in the breadcrumb above the chart. Clicking a breadcrumb segment pops back to that level. Drill state cascades into the detail dialog, forecast, and "Explain this" so they all see the same scoped subset.
Cross-Filter
Click a category on any chart and watch every other tile in the dashboard filter to that selection. This is the typical "filter-by-click" experience from BI tools — built on top of the existing dashboard filter system, no extra configuration needed beyond enabling the toggle.
- Enable from the toolbar via the Cross-filter toggle (☰ icon).
- Cross-filter values stack: clicking another category adds an
AND, clicking the same category again removes the filter. - Active cross-filters appear as a row of chips above the dashboard, each removable individually or via "Clear all".
- Aliased SELECT columns are supported — Qry wraps the original query in a
SELECT * FROM (...) AS _xfsubquery so evenCASE WHEN ... AS departmentis addressable in the outerWHERE.
Click-to-Detail
Click any chart point or KPI to open a modal with the underlying rows that contributed to that value. Useful for "why is this bar so tall?" investigations without leaving the dashboard.
- In the tile config panel → Interactions tab → enable Click to detail.
- Write a
detail_querythat references${detail.where}. Qry resolves the placeholder into a safely-quotedAND col1 = val1 AND col2 = val2chain built from the dimensions of the clicked bar / pivot cell. Drill state is merged in automatically. - The modal opens with a full
EnhancedDataTable(sortable, paginated, searchable).
SELECT order_id, customer, order_date, amount
FROM orders
WHERE 1=1
${detail.where}
ORDER BY order_date DESC
The editor refuses to save a tile whose detail_query doesn't reference ${detail.where} — a query without it would scan the entire table on every click, which is never the intent. Add WHERE 1=1 ${detail.where} (or merge it into an existing WHERE) to enable.
If your main chart query uses computed columns (e.g., CASE WHEN cuenta_mayor LIKE '6%' THEN 'expense' END AS category), the detail query operates on the raw table and doesn't see the alias. Wrap your main query in a CTE and reuse it in the detail query, or reproduce the case expression directly.
AI Assist (per-section SQL writers)
The tile config panel has AI Assist buttons next to four specific concerns. Unlike the general "AI SQL Assistant" on the main query editor, each of these is purpose-built: the prompt tells the LLM exactly what kind of transformation it's doing, what placeholders to use, and what naming conventions to follow.
| Where | What it does |
|---|---|
| Click-to-detail section | Generate the detail query from your main query — mirrors dimensions, adds ${detail.where}, removes aggregates, adds LIMIT 5000. |
| KPI Settings → Period comparison | Add a <metric>_prev column to the main query using ${range.prev_start} / ${range.prev_end} with strict-< semantics. |
| Drill-down section | Rewrite the query as a drill hierarchy (${drill.field} / ${drill.where}) and propose the levels. |
| Cross-filter section | Audit the main query for compatibility (UNION, aliases, schema-qualified columns) and surface findings as warnings. |
All four share the same UI: the section button opens the SQL editor with the AI panel pre-loaded and the kind set. You can edit the suggested prompt before generating. The preview shows what would change, and only after you click Apply does the SQL hit your tile.
Period Comparison
- Save a base query with one numeric metric (e.g.
SELECT SUM(amount) AS revenue FROM orders WHERE order_date BETWEEN ${range.start} AND ${range.end}). - In the KPI Settings section, click ✨ AI Suggest next to "Period comparison".
- AI rewrites the SELECT to use two
CASE WHENaggregates — one for the current range, one for the previous range — with the strict-<boundary onprev_endbaked in correctly. - Set Comparison Field to the new
_prevcolumn (the dropdown will show it automatically).
The prompt explicitly warns the LLM about the half-open window — no BETWEEN, no <= on prev_end — so the generated SQL is portable across BigQuery / Snowflake / Postgres / etc.
Drill-down
- Have a flat aggregated query (e.g.
SELECT region, SUM(rev) FROM sales GROUP BY region). - In the Drill-down section, click ✨ AI Suggest. Default prompt suggests a sensible hierarchy from the schema.
- Preview shows two things: the rewritten SQL (using
${drill.field}and${drill.where}) and a chip list of the proposed levels (e.g.Country > Region > Store). - Apply — the SQL replaces the tile's main query and the suggested levels populate
chart_config.drilldown.levelsso the breadcrumb works immediately. No second config step.
Under the hood: the LLM embeds the level metadata as a -- AI_DRILL_LEVELS: [...] SQL comment that the backend extracts and strips before returning the cleaned SQL.
Cross-filter Audit
This one is a check, not a transformation:
- Open the Cross-filter section on any data tile.
- Click ✨ AI Audit Cross-Filter.
- AI reviews the main query and reports:
UNION/UNION ALL— cross-filter cannot apply (the subquery wrap can't filter post-union).- SELECT-aliased columns — now safe via the subquery wrap, but the audit confirms the alias is well-named.
- Schema-qualified column references — bare names work best for the outer WHERE.
- Findings render inline as warnings; the SQL changes only if the AI suggests a fix. If the query is already cross-filter ready, you get a green "no issues found" pill.
Findings come back via the -- AI_WARNINGS: [...] sentinel and surface in the tile's warnings field — the same channel as the runtime UNION-skip notice, so the rendering is consistent.
AI Analytics
The dashboard editor ships with four LLM-powered features that run on top of the data the user is already looking at. None of them get tool access to your datasources — they only see the rows that the dashboard has already retrieved, so RBAC/ABAC are enforced upstream.
Explain This
Click the ✨ Explain button on any tile to open a side panel where the LLM summarises what the chart shows: notable spikes, comparisons against the rest of the dashboard, anomalies detected by the analytics layer.
- Answer arrives as a streaming, typewriter-style text.
- The LLM is prompted to cite specific tile values rather than generic claims.
- If analytics overlays are active (anomalies / forecast), the explanation references them.
Dashboard Q&A
A chat-style side panel that answers questions about the entire dashboard, not just one tile.
- Open from the toolbar's Ask button.
- Each tile's latest data is included in the prompt, capped per-tile + globally to bound token usage.
- The LLM cites the tiles it used (
referenced_tiles) so the UI highlights which charts back each answer. - When a question can't be answered from what's visible, the LLM says so explicitly and suggests which tile or filter would help.
- Suggested follow-up questions appear under each answer.
Q&A is read-only and stateless — it cannot run SQL against your warehouse. If you want write-mode analysis, send the question through the regular chat.
Anomaly Detection
Toggle on a tile to overlay outliers directly on the chart:
| Method | Best for |
|---|---|
| IQR (default) | Skewed distributions; flags values outside Q1 − 1.5·IQR … Q3 + 1.5·IQR. |
| Z-score | Roughly Gaussian data; flags values beyond a configurable σ threshold. |
| Isolation Forest | Multivariate / non-trivial patterns. Slower; use for ≥100 points. |
Anomalies render as pin markers with a halo and a ⚠ label, coloured by severity. Hover for the value and the rule that flagged it.
Forecast
Add a forecast extension to line/area/bar tiles. Powered by statsmodels Holt-Winters Exponential Smoothing (no Prophet — drop-in compatible, far smaller image footprint).
- Calendar-aware: detects daily / weekly / monthly / quarterly / yearly granularity and steps forward in the same units.
- Configurable horizon (1–N periods).
- Drill-state-aware: when the user drills down, the forecast re-fits to the drilled subset.
- Confidence interval rendered as a translucent band; the forecast itself uses a dashed line continuing the original series.
We evaluated Prophet (added ~600 MB to the worker image), ARIMA (heavy parameter search), and Holt-Winters. The last gives the best size/quality trade-off for the typical dashboard time series (≤ a few hundred points, weekly seasonality, no exogenous regressors).
Exporting Tile Data
Every data tile (chart, KPI, table) has a download button in its header dropdown:
- CSV — UTF-8 with BOM so Excel opens accented characters cleanly.
- XLSX — true Excel file with column widths auto-sized from the data.
Exports respect the current dashboard state — filters, drill level, and cross-filter selections. The downloaded file is the same rows the LLM sees during "Explain this" or Q&A, which keeps cross-channel investigation consistent.
There's a server-side endpoint (POST /api/dashboards/{id}/tiles/{tile_id}/export) so other tools (Lakeflow, scheduled notebooks) can hook into the same exporter.
Versioning and Portability
Two complementary mechanisms for "going back" and "moving the dashboard around":
Undo / Redo (in-session)
While editing, every mutation is recorded as a reversible command — adding or deleting tiles, updating titles or SQL, dragging/resizing, editing filters. Use them via:
- Toolbar buttons (↶ ↷) — disabled when nothing's available; hover to see what would be undone/redone.
- Cmd/Ctrl + Z to undo, Cmd/Ctrl + Shift + Z to redo.
Undo is in-session: it survives until you reload, and unlike checkpoints it's free (no DB writes, no naming required). Each undo makes the inverse server call so the persisted state stays consistent — you can refresh after undoing and the change really is rolled back.
Undoing a delete recreates the tile but with a new UUID. Drill-down and click-to-detail references that pointed at the deleted tile's old id won't reconnect automatically. For operations where you want id-stable rollback, use a named checkpoint instead.
Named Checkpoints (durable)
Long-lived, user-named snapshots of the dashboard's configuration (pages, tiles, filters, settings) stored server-side. Use them for milestones:
"v2 — before margin breakdown redesign" "End-of-quarter snapshot"
From the dashboard's ⋮ menu → Checkpoints:
- Save current state — name + optional description.
- Restore any checkpoint to replace the live dashboard with that state. The current state is dropped onto the undo stack first, so a single Cmd+Z brings it back if the restore was a mistake.
- Delete checkpoints you no longer need.
Checkpoints capture configuration only — they do not include cached query results (dashboard_snapshots) or the public share token. Restoring shape doesn't invalidate the share URL your colleagues are already using.
Owner-only: workspace members can edit the dashboard but only the owner manages its checkpoint history.
Export / Import
Move a dashboard between Qry instances (production → staging, tenant → tenant, dev → demo) without copy-pasting SQL. From the ⋮ menu → Export to file you get a <name>.qry-dashboard.json file containing:
- Dashboard settings (name, layout, filters, refresh interval)
- Every page and tile (titles, queries, chart configs, pivot configs, grid positions)
- A
required_datasourcesblock listing the logical datasource refs the tiles need
What's not in the export: ids, user_id, workspace_id, share_token, cached snapshots, conversation refs — all things that wouldn't make sense in a different instance.
The matching Import button lives on the dashboards list page. The wizard walks through:
- Upload the JSON file. The server validates the schema version and inspects what's needed.
- Map datasources — every logical ref from the bundle is mapped to a local datasource. Exact-name matches are pre-filled; you tweak the rest.
- Confirm — name the new dashboard (defaults to the original name) and import. The new dashboard is owned by you in the target instance.
The importer verifies you have access to every datasource you map to — import can't be used as a permission-escalation vector.
Exports carry a schema_version field. Future versions of Qry may evolve the bundle format; the importer rejects unrecognised versions explicitly rather than silently dropping fields.
Preview Mode
The editor has two modes:
- Edit mode — toolbar, tile config panel, grid handles, AI Assist. Owners and workspace members with edit rights see this by default.
- Preview mode — clean, distraction-free, fullscreen-friendly. Click anywhere to interact (drill, cross-filter, click-to-detail) without entering edit. Non-owners land here by default.
Toggle with the Preview button in the toolbar. Preview mode also drives the public share rendering, so what an external viewer sees is exactly what you see in preview.
Dashboard Settings
Access settings from the editor toolbar:
| Setting | Description |
|---|---|
| Name | Dashboard title |
| Description | Optional description |
| Workspace | Assign to a team workspace |
| Auto-refresh | Set refresh interval (30s, 1m, 5m, 15m, 30m, 1h) |
Best Practices
Dashboard Design
- Use consistent layouts - Align tiles in rows for visual harmony
- Group related metrics - Place related KPIs together
- Limit tiles per dashboard - 6-12 tiles recommended for readability
- Use clear titles - Be specific about what each tile shows
- Add context - Use text tiles for section headers and notes
Query Performance
- Use LIMIT - Restrict row counts (e.g.,
LIMIT 100) - Aggregate data - Use
GROUP BYinstead of raw rows - Add indexes - For frequently queried columns
- Use snapshots - For expensive queries on public dashboards
Refresh Strategy
| Use Case | Recommended Interval |
|---|---|
| Real-time monitoring | 30 seconds |
| Operational dashboards | 1-5 minutes |
| Daily reports | 30-60 minutes |
| Static analysis | Manual only |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Escape | Close config panel |
Delete | Delete selected tile (with confirmation) |
Ctrl/Cmd + S | Save dashboard |
Troubleshooting
Tile Shows Error
- Check the error message displayed in the tile
- Open config panel and review the query
- Click "Run Query" to test
- Verify you have datasource permissions
Layout Not Saving
- Ensure you're the owner or workspace member
- Check network connection
- Refresh the page and try again
Chart Not Rendering
- Verify query returns data (run query to test)
- Check field mappings in configuration
- Ensure value fields contain numeric data
- Try a different chart type
Public Dashboard Shows No Data
- Owner must create a snapshot before sharing
- Snapshot may have expired (7-day TTL)
- Owner should refresh and create new snapshot
Drill Click Reports "Level out of range"
The drill controller blocks clicks that would push past the deepest configured level. If you see this, either add another level to the drill config or guard the chart so its deepest layer isn't clickable. (A 200 ms time guard already swallows accidental double-clicks.)
Detail Modal Says "No rows match"
The detail_query runs against the base table, not the projection produced by the main chart query. If the main query uses computed aliases (CASE WHEN ... AS category), wrap it in a CTE so both queries share the same definitions, or reproduce the case expression in the detail query.
Forecast Returns No Curve
Common causes:
- Too few points — Holt-Winters needs at least 2× the seasonal period of history.
- Constant series — no variance, nothing to forecast.
- Non-temporal x-axis — the x-field has to be parseable as a date / quarter / year. Strings like
"2026-Q1","2026-05","2026"are all handled; arbitrary labels are not.
Limitations
- Maximum 50 tiles per dashboard
- Query results limited to 10,000 rows
- Table tiles display maximum 100 rows
- Public dashboard snapshots expire after 7 days
- Plotly charts require fullscreen modal to interact
- Drill-down and cross-filter are session-scoped — they don't persist to the URL and aren't replayed on public shares (yet)
- Dashboard Q&A is read-only against visible tile data — it doesn't run new SQL against your warehouse
- Forecast requires a parseable temporal x-axis; arbitrary string categories are not extrapolated
Dashboards work great with Python Execution for custom Matplotlib/Plotly charts, Notebooks for scheduled analysis that feeds dashboards, Workspaces for team collaboration, and QRY Nexus for building dashboards from curated Data Products!
For programmatic dashboard management, see the Dashboard API Reference.