Analytics
analytics.polecat.live · Help Reference

Getting started

Analytics lets you design complete analytics dashboards visually — no hand-coding required. Open a browser, choose a data source, drop it onto the canvas, and export a production-ready file in minutes.

Your first sign-in

A welcome screen greets you (by name, when you're signed in as a real user). Its two big cards are the tours:

Below the tours, smaller shortcuts jump straight into a section (New View, Build a dashboard, Bring your data), and a clearly-labeled Skip the tour button lets you go explore on your own. The welcome shows only once; revisit it anytime from Settings → Presentation, whose Welcome tour row carries a Take the tour button.

The left rail — three groups

The left rail: Workspace, Build, and Manage groups, with the workspace backend indicator
The left rail's three groups

Collapse the rail to icons-only with the toggle at its bottom. Your browser's Back/Forward buttons step through sections instead of leaving the app — Back closes an open editor, a zoomed View, or slideshow first.

Two rail items worth calling out

The top bar

The global top bar: section name left, search center, quick actions right
The global top bar

The top bar stays put across every section:

On phones the bar keeps the essentials — section name, search, app switcher, New — with the rest tucked into the rail drawer and the ⋯ More menu.

On a phone, the toolbar lives in ⋯ More

Narrow screens don't have room for the full button row, so the app hides it rather than crushing it — and that includes the builder's own toolbar, which on a laptop sits along the top of Studio. Nothing is lost: every one of those buttons has an entry in ⋯ More that does exactly the same thing. Wherever this page tells you to click a toolbar button, this is the route your phone has instead:

Keyboard shortcuts are unaffected — if your phone or tablet has a keyboard, ⌘ S / Ctrl S and friends still work.

Quick import — file to dashboard in one drop

Home’s quick-action cards, with Quick import highlighted as a file drop target
Quick import: drop a file, get a dashboard

Home's Quick import card is the fastest way in with your own data. Drop a .csv, .json, or .xlsx (Excel — its first worksheet is read) onto it (or click to browse) and the app:

Files stay under 2 MB and inline (fully offline); for bigger files, host them and use the DuckDB (remote file) connector. The same affordance lives on the builder's empty canvas — an Import a file button, or drop the file straight onto the canvas.

New dashboard from Dashboards: a "+ New dashboard" button on the Dashboards page's own toolbar opens Studio on a fresh blank dashboard, next to the view toggle/Select/Compare — the same starting point as the topbar's "New ▾" menu or Repository's "+ New ▾ → New dashboard", just reachable without leaving the page.

Export/Import repository: tucked behind the Dashboards page's More (⋯) menu — handy for moving work to another browser/device, or as a manual backup:

Workbooks

File dashboards into named collections on the Repository page:

Folders (alongside workbooks)

Dashboards also file into folders — the same nested "/"-path folders your datasets, connections, and jobs use (e.g. "Finance/2026"):

Select multiple / bulk actions: click Select on the Dashboards page to enter multi-select mode — a checkbox appears on every tile/row, and tapping anywhere on a card or row toggles its selection instead of opening it. A bar above the list shows how many are selected with Select all / Clear, a Move to folder… button that files every selected dashboard in one go (the same folder browser the per-row folder button opens — pick a folder, create a nested one inline, or choose "No folder" to un-file them), and a Delete button that removes every selected dashboard after a confirmation (the toast that follows carries an Undo button for a few seconds). Sample-pack dashboards can be selected and deleted individually like any other — removing one just drops it from your workspace; remove and re-add the sample pack in Settings to restore the full set. Click Select again (now labeled Cancel) to leave select mode.

Compare dashboards: the Repository page's "Compare dashboards…" button opens a picker for any two of your saved dashboards — a live preview of each renders side by side (the same render every export/preview uses, so it's a genuine "which of these looks better" comparison, not a thumbnail), with a plain-English summary of what differs between them underneath. This is distinct from a dashboard's own Version history (below), which only ever compares a dashboard against its own past checkpoint — Compare dashboards is for two different saved dashboards, e.g. judging two drafts against each other.

"Changes since you were last here": a recent-dashboard card on Home or Repository shows a small "N changes since you were last here" note whenever the dashboard has moved on since the last time you actually opened it — added a View, changed the accent color, whatever Version history's own plain-English diff would say. Hover the note for the actual list of changes. It clears the moment you reopen the dashboard (that becomes the new "last here"), so it only ever nudges you toward what's new since your last visit, not a running history.

Step 1
Pick your data
Browse the Data panel on the left. Search by name, table, or column. Drag a query onto the canvas to create a new chart View.
Step 2
Configure the chart
Click a View on the canvas to select it. The Inspector (right side) lets you choose a chart type, bind columns, and tune visual options.
Step 3
Export and deploy
Use Export ▾ — ⋯ More → Export… on a phone — to download a self-contained dashboard .html, or a full bundle (.html + the editable .studio.json spec) — host it anywhere static pages live.
⚡

Auto-build: click New ▾ → Auto-build to instantly scaffold a complete dashboard from any set of queries — KPIs from KPI data accesses + a chart per chartable DA, all in one click. Edit from there.

📲

Install it: the Studio is an installable, offline-capable app — most browsers offer "Add to Home Screen"/"Install app" from the address bar. Once installed (or even just visited once), a background service worker caches the app shell so it keeps working with no connection; it always prefers a fresh copy over the network first, falling back to the cached one only when offline. If that cached copy ever gets stuck — an update banner that keeps coming back however often you reload — Settings → App → Hard reset throws it away and fetches everything fresh, without touching anything you have made. "Clear local data" (⋯ More menu) also clears this cache, but it wipes your workspace with it, so reach for the hard reset first.

Home — instant analytics

Home is where the app opens. The top of the page is a row of quick-start cards — one per way to begin — and everything below them is your own content, live.

The quick-start cards

Under the “Welcome back” greeting Home lays out a card per starting point. Clicking one takes you straight there; nothing is created until you save.

A viewer-role account sees only the cards it can act on: New dashboard, Quick import, Sample dashboards and Take the tour all route into the builder, which viewers never enter, so Home leaves them out rather than offering a dead click.

A rotating tip sits under the cards; the › button on it steps to the next one.

Your content, below

Each content section is hidden while it is empty — except Dashboards, which always renders, so a brand-new workspace still has somewhere to land:

In Simple mode the app boots to Home whenever you have featured content, and to Quick Views when you don't; your own last-used section always wins.

Open in viewer (the eye icon)

Every dashboard card or row carries a small eye icon — it opens the dashboard read-only, full-page, in a new tab: the same live, interactive renderer (filters, cross-filter, provider toggles all work) with none of the builder chrome. Handy for sharing with someone who should read a dashboard, not edit it.

Light or dark in the viewer follows you, not the author. A dashboard's Appearance setting (Dashboard inspector → Appearance: Light, Dark or Auto) decides how the dashboard looks as a finished piece — but inside this app the viewer renders it in your light/dark theme instead, because a dark app wrapped around a light dashboard just looks broken. Nothing about the dashboard is changed: switch your own theme and the viewer follows on the next open. Files you hand out are untouched by this — a downloaded Dashboard (.html) and a PDF always look exactly the way the author set Appearance, wherever they're opened, so what lands in someone's inbox or on a website is predictable — unless the author picked Auto, which is the one Appearance that asks the file itself to adapt (see "Appearance" below). The builder's live preview also keeps showing the authored Appearance, so you can see what you're making.

How dashboard filters find their data: a filter applies to a View when that View's dataset either declares the filter as a query parameter (live SQL engines substitute it server-side) or simply has a column with the same name — the rows are then filtered to the picked value. A filter named Since … keeps everything from the picked value onward (so "Since year 2020" shows 2020 to today, not just 2020). This works the same on live data, file datasets, and sample data.

The viewer's top bar

Left to right it carries a back link to Analytics, the dashboard's title, a Viewer — read-only badge that says plainly what this page is, and these actions:

On a phone the bar goes icon-only. At 640px and narrower the bar has no room for all of that, so the Viewer — read-only badge is dropped and every button loses its text label — Save a copy, Export and Edit in Dashboard Builder become their icons alone, each keeping its name as its tooltip and its screen-reader label. Nothing moves into ⋯ More here: that is the builder's toolbar (the toolbar lives in ⋯ More), and the viewer has no ⋯ menu at all.

That Export button offers three of the formats Studio does: Dashboard (.html) — a self-contained file you can drop on any static host or open offline — PDF (print), and the Editable spec (.json). The office formats and the bundle are the builder's Export ▾ menu only (see "Exporting" below). A sample or demo dashboard exports with its data baked in, so the download is complete on its own; a dashboard backed by a real data source keeps querying that source live, in the viewer and in the exported file alike.

Quick Views (Explore) — dataset-first Views

Quick Views (left rail, Build group — the section previously named Explore) is the fastest path from data to chart, built for non-experts:

  1. Pick a dataset on the left — your workspace datasets first, sample data below.
  2. See its rows as a table, choose a chart, adjust the column mapping — the live preview is the real dashboard renderer, so what you see is exactly what a dashboard shows.
  3. Give it a name and Save View.

The dataset picker is a real navigator, not a flat list: datasets group into their folders (nested via "/"), sample data groups by set (collapsed once you have data of your own), and every branch collapses with a click. Searching flattens the tree to plain matching rows — finding something by name never depends on knowing where it's filed.

View Builder — pivot and crosstab, no code

The View Builder: dataset outline on the left, fields on the Columns and Rows shelves, the live result in the middle
The View Builder

Views (left rail, Build group) is Quick Views' power-user sibling: a visual pivot/crosstab query builder.

The dataset navigator (left pane)

Fields and shelves

Click a dataset and its columns appear as chips — # marks a numeric field, a a text one. Click a chip (or drag it) onto the Columns shelf and the result table renders live in the middle. Numeric fields aggregate automatically as SUM — the little aggregation badge on the shelf chip switches to AVG, MIN, MAX, MEDIAN, or COUNT. With only dimension fields on the Columns shelf you get a plain selection of those columns; add a measure and the dimensions group it. Some numbers aren't quantities — a FIPS code, a year, an ID — so the aggregation dropdown also offers CATEGORY, which groups by that field instead of summing it; id-like numeric columns (ending in _fips, _id, or plain id) default to Category the first time you drop them, rather than SUM.

When you save, the Title on dashboards field names the View where it sits on a dashboard — it defaults to (and keeps tracking) the View's name until you set your own.

Drop a field on the Rows shelf (or use a chip's ⇄ button) and the table pivots into a crosstab:

The chart strip above the result switches how it draws: Table (the full pivot), Bars, Stacked bars, Line, Stacked area, Donut, Heatmap, Sankey, Map, Scatter, Quadrant, or KPI. Charts draw your computed numbers through the real dashboard renderer — Bars and Donut chart the first dimension against the first measure (COUNT of rows when no measure is picked), and Heatmap lights up when you have a field on Rows plus a plain field on Columns, drawing exactly the crosstab as a color matrix. A chart that needs something you haven't added yet is simply disabled, with the reason in its tooltip.

Sankey reads the same two shelves as the Heatmap, in flow terms: the field on Rows is where the value comes from, the plain field on Columns is where it goes, and the measure beside it is the width of the ribbon. So "which agency paid which contractor, and how much" is a Rows field, a Columns field and a SUM — the same pivot the Heatmap draws as a colour matrix, drawn as flows instead. Filter the measure to keep it readable: a diagram with a few dozen ribbons is a picture, one with several hundred is a hairball.

The chart canvas fills to the bottom of the screen by default (like the datasets pane next to it) and is resizable: drag the slim bar under it to make it taller or shorter, or the bar on its right edge to make it narrower or wider. The size you set sticks across visits; double-click a bar to snap that direction back to automatic (fill to the bottom / full width). On a phone the canvas just fills the width — no drag bars.

The chart fills the canvas. Drag the canvas taller and the chart is redrawn at the new height rather than leaving an empty band underneath — it redraws when you let go of the bar, not on every pixel of the drag. The canvas is a preview viewport, though, not part of the View: it is one setting for this browser, shared by every View you open here, so saving a View keeps that View's own height and never picks up the size you last dragged. To change the height a View is stored and exported at, set it where every View's height lives — Height (px) in the dashboard builder's Inspector, or by dragging the View's bottom edge there.

The Datasets pane resizes the same way: drag its right edge anywhere from 200 to 480px when long dataset names get cut off — the width sticks across visits. The chevron in its header collapses the whole pane to a slim vertical strip (more room for the canvas); click the strip to bring it back.

Drop a file to start instantly. Drag a CSV, TSV, JSON, or Excel (.xlsx) file anywhere onto the View Builder: it becomes a real dataset (it appears in your Datasets list like any other) and the builder inspects the columns and opens the most interesting view on the canvas — a map for geographic ids, a trend line for time data (color-split when a small category column exists), bars for categories, or the raw table when nothing pairs up. The shelves arrive pre-filled, so keep editing from there or hit Save View.

Switching datasets never loses your work. Each dataset keeps its own work-in-progress draft: click another dataset and your shelves, filters, calculations, and chart pick are stashed; click back and they return exactly as you left them (drafts survive a reload too). Datasets carrying a draft show a small dot in the pane, so you can build on several and walk through them one by one. The Clear canvas button at the right end of the chart strip resets just the current dataset to a clean slate.

KPI is the odd one out: no dimension at all, just one rolled-up headline number (Save adds it to a dashboard's KPI row, not its View grid). Put any field on a shelf — a measure aggregates across every row, or a plain field falls back to COUNT — and it collapses the whole filtered result down to a single value, the same grand-total rollup the Table chart type would show with nothing on Rows and one measure on Columns.

Scatter needs two measures instead of one: put a dimension on Rows or Columns plus two or more numeric measures on Columns, and it plots one point per dimension value — the first measure on the x-axis, the second on the y-axis. It's the same one-dimension basis Bars and Donut use, just widened to carry two measures instead of one, so it's disabled until a second measure lands on the shelf. With Scatter picked, a Trend line checkbox appears next to the chart types: it draws the least-squares regression line through the points (the dashed line), and it saves with the View like any other setting — a View authored with one opens here with the box already ticked.

Quadrant takes the same two measures and splits the plot into four labelled zones, colouring each point by the zone it lands in — the "where does this one sit?" read that a plain scatter leaves to the eye. It splits at the midpoints here; the thresholds and the four zone labels are edited in the Dashboard inspector, and a View that already has its own keeps them when you open and update it from the builder.

Map draws a US choropleth from your geographic field (region ids — FIPS county code, state FIPS or postal code, USDA district, watershed/HUC8, congressional district, or ZIP) against the first measure — the geo-looking field wins the map's id role from either shelf, so a year sitting first doesn't steal it. The Region scale picks itself from that field's name and values (a state_fips column opens as States, a huc8 column as Watersheds) — the Auto entry in the Region-scale control next to the chart types shows what it inferred, and picking a scale there overrides it. Renderer and styling still live on the saved View itself like any other map. Put a field on the Color shelf and the map switches to per-region series instead: a long table of region × series × value that plugs straight into the Studio ensemble channel, so an Ensemble chart's provider toggles elsewhere on the same dashboard re-color it live.

Line, Stacked bars, and Stacked area all draw multiple series when the shelves support it: pivot a field on Rows against a plain field on Columns (a crosstab) with one of the three picked, and every Columns value draws its own line / bar segment / band against the Rows field. Or skip Rows and put two or more measures on Columns — each measure draws as its own series, grouped by your one dimension. Anything richer (two Rows fields, or a crosstab with more than one measure) still falls back to a single series on the first dimension and measure — the same one-dimension basis Bars and Donut use.

The Filters shelf narrows the source rows before anything computes — the pivot, every chart, and the row count in the status line all see the same filtered set. Add a filter by dragging a field there or with the + Add filter picker: a text field filters by a searchable value checklist (All/None + pick what you want), a numeric field by a min–max range (leave a bound blank for open-ended). A freshly added filter shows all and changes nothing until you edit it; active filters highlight their chip and the status line reads "N of M source rows (filtered)".

The Color shelf makes color a first-class encoding, not just a chart-type default: drop a category there (or pick one from + Color by…) and Bars gets a distinct color per bar instead of one flat color — the same per-category coloring Donut already draws by default. With nothing on the Columns shelf, dropping a field on Color also splits a Line chart into one line per category, standing in for a Columns split field. Alongside it, a palette picker swaps the chart's color family — the same presets the main Dashboards builder's "Series palette" control uses — so a View can preview in a different color scheme without leaving Build.

Calculated columns: the + calc… chip at the end of the selected dataset's column list opens an editor with a fresh blank row ready, where you define new columns from formulas — =[revenue] / [acres], =([a]+[b])*100, or the running helpers =pctChange([sales]) and =movingAvg([sales], 3). It's the same safe formula language the Studio data-source editor uses. A calculated column appears in the outline with an = marker and from there behaves like any other field — put it on a shelf (numerics default to SUM), filter by it, chart it. To change one, click the ✎ on the column itself — it opens the same editor with that formula focused, and it stays available after the column is on a shelf. Renaming a column there keeps it on the shelves and filters that use it. A calculated column can't shadow a real column's name, and deleting one cleanly removes it from any shelf or filter that used it.

Save View (top right) saves the result as a View with whichever chart type is selected — filters and calculated columns included — and it appears in the Views section like any other. Opening it from there returns it to Build with its dataset, shelves, filters, calcs, and chart restored (Views made in Explore keep opening in Explore). The Save dialog offers a ✨ name-suggest button and a Folder field — type a new folder, pick one from the list of folders already in use, or click Browse to navigate the existing folder tree, the same picker every other Folder field in the app uses.

A saved View Builder View shows its real computed result everywhere it's used: dropped on a dashboard, pinned to Home, or opened in Quick Views, the app re-runs the View's dataset, filters, and calculations and renders the actual numbers — not placeholder sample rows.

Sample packs

Sample packs (installed from Settings) are ready-made demo content you can install or remove. A pack can add dashboards, datasets, connections and jobs — sample content, never your real data — and Remove takes back exactly what Install added. Everything a pack adds is filed in the pack's own folder (Conservation Insight, Data Management, Market Coverage, Federal Contract Awards, Campaign Finance, Where America Moved) across every section, and its raw sample tables only appear in the dataset pickers while the pack is installed — an uninstalled pack leaves no trace. The packs are the only sample-content switch there is — Settings used to carry a separate "Sample content" mode toggle that hid everything at once, and it is gone: remove the packs you don't want (or all of them, for a completely empty workspace) and their dashboards, datasets and raw sample tables go with them. Nothing you made is touched.

Where a pack's data comes from is on its card. Every pack states its source in one line under its description. Conservation Insight and Data Management read "Data: synthetic — generated in the app, not real observations", because that is exactly what they are. A pack built on a real public dataset names the dataset, its licence and the date it was retrieved instead, and repeats that line in the subtitle of every dashboard it installs, so the attribution travels with the work even after you export it.

Removed the wrong pack? Undo. Remove shows its toast with an Undo button for a few seconds. One click restores every dataset, View, dashboard, connection and job the pack owned — under the same ids, with any edits you'd made to them intact — and marks the pack installed again.

Jobs — prep & rollup

Jobs (left rail) prep one dataset before it's charted: rename or cast a column, derive a new one from arithmetic on two others, filter rows, roll everything up with a group-by aggregate, and join or union in a second dataset. Run a job and the result is saved back as an ordinary dataset — ready for Quick Views, the builder's Data panel, or any dashboard — and re-running the same job updates that dataset in place, so an annual data refresh is a single click.

The builder

The workspace is divided into three resizable panes. Each pane can be collapsed to a labeled rail by clicking the ‹ / › collapse button.

Polecat apps switcher: the app bar (top of the screen, just left of New ▾) carries a waffle (3×3 grid) button that opens the Polecat suite switcher — one-click jumps to the other apps in the family (Chat, JobTracker, AutoSelector, Relay, Games, Manager, Model Server), with this one highlighted as the app you're already in. It's the same switcher every polecat.live app carries, themed to whichever Studio look you're using.

What's new: the What's new button in the top bar — present on every section, not just in the builder — opens the full release feed in a right-hand pane: every version, newest first, with live search (matches highlighted) and Central-time stamps. A small dot on the button means there are releases you haven't seen yet; opening the pane clears it. Click the button again, the ✕, Escape, or the backdrop to close it. On a phone the top bar gives that icon's room to the section name, so the route there is ⋯ More → What's new — see On a phone, the toolbar lives in ⋯ More.

Three panes

The builder opens clean: both side panes start closed so the dashboard gets the full width — pop them open with the edge chevrons when you need them. Prefer them always open? Flip Open the builder with side panes in Settings and every visit starts that way.

The View inspector is context-aware: interaction sections like Drill-through, Detail drawer, Cross-filter, Conditional formatting, and Color scale only appear when the selected chart type actually supports them (e.g. Conditional formatting shows for Bar/Donut/Treemap/Lollipop but not for Table or Line — clicking a table row instead opens the Detail drawer). This keeps the inspector focused on settings that do something for the current chart.

Renaming a dashboard: the dashboard title in the toolbar above the live preview renames in place — click it and it becomes a text field (Enter or clicking away commits, Escape cancels). The Dashboard inspector's Title field is the same value, edit whichever is closer. The Title (the display name shown in the dashboard's header/banner) and the File name (stem) (the lowercase-with-dashes name used for exported files, e.g. my-dashboard.html) are two independent fields right below it, so you can rename either without the other changing.

Header logo: the Dashboard inspector's Header logo field (below Subtitle) uploads a PNG/JPG/SVG (up to 200KB) that replaces the default "P" mark in the dashboard's banner, in both the live preview and the exported Dashboard Framework — a per-dashboard brand mark, separate from the app-wide rail branding in Admin. Leave it blank to keep the default mark.

Header link: the Header link URL field right below it makes the logo + title in the banner clickable, opening that URL in a new tab — handy for linking back to a company site or portal. Leave it blank to keep the banner as plain, non-clickable text.

Appearance (Light · Dark · Auto): the Appearance picker in the Dashboard inspector decides the light/dark of this one dashboard — in the live preview and in everything it exports. Light and Dark bake that choice in: the file looks the same everywhere it's opened, which is what you want for a deliverable that lands in an inbox or on a website. Auto (match the reader) bakes no theme at all — the dashboard follows whoever opens it: the page it's embedded in when it can read that page's theme, and otherwise the reader's own system light/dark setting. It's exactly the same file either way; it just decides when it opens. New dashboards start on Light — Auto is something you turn on deliberately.

Show dashboard header (embed mode): the Header toggle in the Dashboard inspector. Turn it off and the entire title banner and description bar disappear from both the live preview and the exported .html, leaving just the KPIs and Views — a clean, chrome-free dashboard you can drop straight inside your own page. Turn it back on and the title, subtitle and description return, all still editable in the inspector.

The header as an object: click anywhere on the title banner in the live preview (not on one of its buttons) to select it, the same way clicking a View or KPI tile does — the Inspector switches to a dedicated Header view with quick Title/Subtitle/Alignment fields and a ✕ button that hides the whole banner (the same effect as the Show dashboard header toggle above). Double-clicking the title or subtitle text directly still edits it in place without needing to select first. Logo, link, and light/dark stay in the Dashboard inspector (click "‹ Dashboard" at the top of the Inspector to get back there).

Alignment: in that same Header view, the Alignment picker (Left / Center / Right) moves the brand mark, title and subtitle within the banner. Left is the standard flush-left layout. Center and Right shift that block toward the middle or the icon cluster on the right — the info/print/waffle icons always stay pinned to the far right either way.

Title size: right below Subtitle, the Title size picker (Default / Small / Large / Extra large) resizes just the banner title text — handy for a dense multi-KPI ops board (Small) or a single-hero exec dashboard where the title should dominate the banner (Extra large). Leave it at Default to keep the standard weight/size.

Subtitle style: next to Title size, the Subtitle style picker (Normal / Italic / Bold / Bold italic) adds emphasis to just the banner subtitle — e.g. Italic for a light tagline, Bold for a subtitle that should read almost as loudly as the title.

Card style: below Subtitle style, the Card style picker chooses the render mood for every chart card and KPI tile on the dashboard. Raised (default) keeps the standard shadow, glass-edge highlight, and hover lift. Flat / minimal strips all three for a quieter, editorial look — same data and layout, just a calmer surface treatment for a boardroom setting. Sketch / hand-drawn swaps the shadow for a dashed border and a wobbled, asymmetric radius for a whimsical, hand-drawn mood.

Share this dashboard

Copy shareable link (in the Dashboard inspector) encodes the whole working dashboard — Views, KPIs, filters, style — into a #share=… link, no file, no server. Opening it in any browser reopens the exact dashboard in the builder — handy for handing a work-in-progress to a teammate.

Version history

Every Save (topbar button, ⋯ More → Save on a phone, or Ctrl/⌘+S) keeps a timestamped checkpoint of the whole dashboard — up to the last 10 per dashboard, stored locally on this device:

Dashboard theme

The Dashboard settings inspector: Dashboard theme, Accent color, and Series palette swap the whole look in one pick
The Dashboard theme picker — one pick swaps the whole look

At the top of the style section, the Dashboard theme picker swaps the whole look — background, View, text, brand, and all ten chart series colors — in one click, for the preview and the exported dashboard alike. Every curated theme's series palette is validated for contrast (WCAG AA) and colorblind safety in both light and dark mode:

Good to know:

Header background color: further down, below Accent color, the Header background color picker sets a flat fill for the banner itself (the default is a navy gradient) — text color auto-adjusts for contrast (dark text on a light pick, white on a dark one), so it's always readable. This is separate from Accent color, which only tints the bottom border plus chart/button accents throughout the dashboard. Click "Reset to default" to go back to the standard navy banner.

Edit JSON spec (power users)

The Edit JSON spec… command palette entry (⌘K / Ctrl K) opens the whole working dashboard as raw, editable JSON — Views, KPIs, filters, style, everything. Useful for bulk edits, scripting a change outside the app, or seeing exactly what the builder tracks.

Build progress & Checks

The top of the dashboard inspector shows a small ring + checklist tracking five well-rounded-dashboard milestones — a real title, a View, a KPI, a filter, and a touch of your own style. It's purely encouraging (an empty dashboard is perfectly valid) and collapses to a one-line "nice work" note once every milestone is met.

The Checks section right below it is different — it only flags real problems:

Drag and drop

Auto-arrange: the Layout field in the Dashboard inspector (next to Grid columns) has an Auto-arrange button that reflows the existing Views for you — chart types with a lot of horizontal detail (Table, Text/annotation, Sankey, Chord, Calendar heatmap) get a full-width row of their own, everything else defaults to a single column, and Views sharing a tag are grouped together. A quick starting point for a first draft; drag-resize still works normally afterward.

Undo / Redo

Every structural edit (add, remove, reorder, resize, rename) is snapshotted. Use Ctrl Z / ⌘ Z to undo, and Ctrl Shift Z / ⌘ Shift Z — or Ctrl Y / ⌘ Y, the Windows alias for the same action — to redo. The ↶/↷ buttons in the topbar work too (they only show while Studio is open; on a phone they are ⋯ More → Undo and ⋯ More → Redo). Text-field edits are not tracked individually (to avoid flooding the history).

Sample dashboards

The bundled sample dashboards — a curated, most-spectacular-first gallery spanning operations, engineering delivery, finance, marketing & growth, reliability, governance, compliance, quality, pipelines, storage, and cost, together covering all 54 chart types at least once (the newest — the Metrics wheel — in the Conservation pack’s own System Metrics dashboard) — live in two places: Home's sample gallery (click a tile to open it in the builder) and the Dashboards section under the Sample packs chip. A great way to explore what's possible before building your own. (The old Studio "Examples ▾" toolbar menu is gone — same dashboards, better homes.)

+ Import from URL… (in the Open-dashboard picker's footer) loads a dashboard from any public link to a .studio.json file — a GitHub raw link, a gist, a static host. A plain client-side fetch, no backend, no account:

Slideshow & story mode

⋯ More → Present → Slideshow cycles through every View one at a time, full-screen — great for a stakeholder walkthrough:

Slide caption (View inspector, below Note) adds narration that appears only in Slideshow — one beat of the story per slide (e.g. "Revenue held steady, but churn ticked up in March"). Distinct from Note, which is stakeholder context shown everywhere; Views without a caption simply show no caption bar.

Turn on Slide emphasis (right below Slide caption) to have that View's slide play a brief zoom + glow entrance the moment it appears — a light touch of choreography that draws the eye to the beat that matters most, replaying each time you return to that slide. Once it's on, Pan X / Pan Y sliders appear too — drag them off-center to anchor the zoom toward a specific spot in the chart (a spike near the edge, say) instead of dead center.

Dashboard filters

The Filters section of the Dashboard inspector (◈ +) adds a dropdown filter chip above the Views. Click + to add one, then click the chip in the live preview (or its row in the list) to open the Filter inspector:

Cascading filters: if a filter's Options query is itself a parameterized data access (it takes its own ${param}), its choices refresh automatically from whichever upstream filter supplies that parameter — e.g. a Region filter narrows a State filter's options to just that region's states. The Filter inspector notes when a filter is wired this way.

Template variables

Write {{key}} anywhere in the dashboard's Title/Subtitle or a View's Title/Note, then define matching entries in the Dashboard inspector's Template variables section — each substitutes its saved value in the live preview and every export.

Built-in dynamic tokens

These need no variable — write them into a dataset's SQL/query (or a title) and they resolve fresh on every run, so relative-date filters stay current on their own:

So WHERE order_date >= '{{today-30}}' is always "the last 30 days." The Date token button on the dataset builder's query field drops any of these at your cursor; defining a real parameter or variable of the same name overrides a built-in.

Ensembles & scientific honesty

When several sources estimate the same thing — several vendors' models, several surveys, several labs — the Ensemble (common estimate) chart and the Map (US choropleth) chart are built around one rule: the common estimate is the product, not a leaderboard. The sections below explain the design choices behind that rule and how to read (or build) an honest ensemble dashboard.

The common estimate is bold; providers are supporting evidence

On both charts, the combined value — computed across whichever sources are currently toggled on — always renders as the boldest, most prominent element: a thick line on Ensemble, the fill color on the map. Which combination that is, is yours to set, and the two charts ask it differently: the Ensemble chart's Common estimate option offers Median (recommended) and Mean, while the map's Combine duplicate rows by option — how several rows for one region become one color — offers Median (common estimate), Mean, Sum, Min, Max and Last. Both default to the median, and the median is what this page's honesty argument is written around: it is the choice a single outlying provider cannot drag. The bold line is named by the chart's Estimate label option — Common estimate unless you change it — and that name is what the legend, the hover tooltip and the downloaded data all print, so what you read follows the setting instead of assuming a median.

Individual providers draw thin and muted (hollow dots, low opacity) — present so you can inspect the underlying evidence, but never competing visually with the estimate itself; the Show provider series option hides them when you want the estimate alone. Toggling a provider off (click its chip under an Ensemble chart, unless the Provider on/off toggles option is off) removes it from the combination everywhere it's used, including any map on the same Ensemble channel option — both charts have that option, and the map also needs its Provider / series column mapped. Both recompute and re-render live from the same reduced set.

The agreement band is a confidence signal, not decoration

The translucent band around the Ensemble chart's estimate line — drawn by the Agreement band (confidence) option, which can also turn it off — spans the full range of the toggled-on providers at each point. Read it literally: a tight band means the sources agree (high confidence in the estimate there), and a wide band means they don't (treat that point with more caution). It is not a stylistic flourish — it's the chart's way of showing uncertainty honestly instead of hiding it behind a single confident-looking line.

A reference series is context, never the estimate

Both charts support an optional reference series — the Ensemble chart's Reference series (excluded from the estimate) option (e.g. an independent census or ground-truth figure) — drawn as hollow markers, visually distinct from the provider lines and the estimate. A reference series is deliberately excluded from the combination — it's there to let a viewer compare the ensemble's estimate against an outside benchmark, not to be folded into the estimate itself.

No-data is shown, never guessed

The choropleth renders regions with no data as a hatched "No data" texture rather than leaving them blank (easy to misread as zero) or interpolating a value (which would misrepresent coverage). Combined with the provenance popover below, a viewer always knows exactly how much of the map is real data versus gaps.

Checking the honesty story: the ⓘ Sources popover

Both charts have an ⓘ Sources button next to their legend — a popover answering "how much of this can I trust?":

The popover stays open while you read it (unlike a hover tooltip) and works identically in an exported dashboard.

Handing off the underlying numbers

Both charts' Download data button (the same on-canvas control every View has — see "Downloading a View's image or data" below) exports exactly the selection currently shown — the map's region id/value pairs post-aggregation, or the Ensemble chart's long-format label/provider/value rows for the toggled-on providers plus the computed estimate (under whatever name the Estimate label option carries) and any reference series — instead of the raw bound query. Re-download after toggling a provider and the file reflects the new selection — a quick way to hand a stakeholder the same numbers the chart is drawing from.

🌾

Worked example: install the Conservation Insight sample pack (Settings → Sample packs) for a complete, ready-made illustration of everything on this page — four pinned Ensemble Views (one per conservation practice) and a featured dashboard pairing them with a provider-aware county choropleth, all built from synthetic, clearly-labeled sample data.

Chart types

Maps

Map (US choropleth)
US regions colored by a value — counties (FIPS), states, USDA crop-reporting districts, watersheds (HUC8, nationwide), congressional districts (119th Congress, nationwide), 5-digit ZIP codes (ZCTA, nationwide), or your own custom regions ("these counties = this territory" — the Inspector's Region scale > Custom regions lets you Import a CSV of two columns, county FIPS and region name; no new geometry ships, the app merges the existing county shapes per region the same way it merges them into USDA districts, and your value data's region-id column should then use those same region names). Bind a region id column and a value column; when several rows land on one region they combine by the median by default (a single best common estimate). Optionally map a provider/series column and the map joins an ensemble channel: the provider toggles on an Ensemble chart sharing that channel re-color the map live, from the same median. Regions without data render as a hatched "No data" texture, a state-border overlay keeps orientation, and the map auto-zooms to the regions that carry data. Exported dashboards inline the geometry, so maps work offline and from a plain .html file. A Renderer option picks between the built-in renderer (light — the smallest export) and Interactive GL (smooth pan & zoom at any polygon count, with zoom buttons, a pan nudge-pad (up/down/left/right), and hover highlight; adds ~1MB of MapLibre to that dashboard's export, and falls back to the built-in renderer wherever WebGL is unavailable). The View's on-canvas Download data button exports the region id/value pairs currently shown (post-aggregation, post-selection) instead of the raw bound query. An ⓘ Sources button opens a provenance popover showing what fraction of regions actually have data and, when a provider/series column is mapped, each provider's own region count (struck through when toggled off) — so the map's honesty story is always one click away.

54 chart types are available, grouped by purpose. Select the chart type in the View inspector after clicking a View on the canvas. Every card below is titled with the name the picker itself prints — the same name the ⓘ docs link on a gallery card opens it by, and the same name a View's chart-type filter pill carries — so a name you read here can be typed straight into the gallery's Search chart types… box and will find its card.

Not sure where to start? Once a View has a query bound, a "Recommended for this data" strip appears above the full gallery with 1–3 suggested types (e.g. Line for a date column + a number, Donut for a low-cardinality category) — each button explains its "why" on hover and switches the chart type on click.

Once you're in a chart type's own options (below the gallery), common toggles like Sort by value, Show legend, Smooth curve, Show data points, Show value/label, Show %, and Rotate labels carry a small glyph next to their label — hover it (or Tab to it) for a one-line explanation of what the toggle actually changes. Sort by value, Smooth curve, Show legend, Show data points, Show value/label, and Rotate labels go a step further with a genuine Off → On picture — two tiny side-by-side diagrams showing exactly what the toggle redraws, not just a sentence about it.

Comparison

Bar chart
Side-by-side bars for comparing categories; horizontal or vertical. Options: sort bars by value (largest first), toggle the value labels, and (vertical layout only) a linear/Holt/Holt-Winters trend line fitted across the bars.
Lollipop chart
Dot on a stem — a cleaner ranked-list alternative to bars.
Radar / spider
Polygon overlaid on concentric rings; great for multi-metric profiles. Options: fill polygons, show/hide the legend, and show/hide vertex dots.
Metrics wheel
Sectored radar for a system-health snapshot: one score per metric on a circular axis, metrics grouped into tinted category sectors, a numbered rim, and a grouped legend decoding the numbers. Options: axis max, legend, value format.
Waterfall
Running total with cumulative deltas; rises green, falls red.
Funnel
Stage-to-stage conversion; bars shrink proportionally to conversion rate.
Gantt / Timeline
Horizontal floating bars spanning a start-to-end range — tasks, phases, and project schedules.
Dumbbell chart
Gray start dot + colored end dot per row; connector green = improvement, red = decline.
Marimekko
Variable-width stacked bars, also called a Mekko: column width = category share, height segments = composition.
Diverging bars
Positive bars extend right, negative bars extend left from a shared zero baseline.
Parallel coords
Multi-dimensional entity profiles across N vertical axes (a parallel-coordinates plot) — each row is a polyline.
Radial bar
Concentric arc tracks where arc length encodes value — striking for ranking a handful of key metrics in a circular layout.
Population pyramid
Mirrored horizontal bars from a shared centre axis — compare two groups (e.g. Female / Male) across shared categories.
Pareto chart
Descending bars + cumulative % line (80/20 rule) — instantly shows which vital few categories account for most of the total.
Grouped bars
Multiple series side-by-side per category — ideal for Q1/Q2/Q3 by Region or Budget vs Actual vs Forecast by Department. Options: rotate labels and toggle per-bar value labels.
Quadrant chart
2×2 matrix: position items on an x/y scatter plane divided into four labelled zones by configurable threshold lines. Perfect for BCG growth-share, effort/impact prioritisation, and risk/probability grids.

Composition

Donut / pie
Part-of-whole with a center total or caption label. Options: sort slices largest-first, show/hide the legend, and an adjustable inner-radius % (thin ring to full pie).
Stacked bars
Multi-series stacked on one axis; composition across categories. Options: sort categories by total, show/hide per-segment value labels, and a linear/Holt/Holt-Winters trend line fitted over each category's stack total.
Treemap
Nested rectangles sized by value; drill into categories at a glance. Options: show/hide the in-tile label, and show each tile's % of total instead of its raw value.
Sunburst
Hierarchical arcs; single-ring or two-ring (group + item) mode.
Polar area
Equal-angle wedges where area (not radius) encodes value.
Packed bubbles
Force-directed bubble cluster; circle area ∝ value — which items are biggest?
Word cloud
Text items sized by numeric value (log scale) and placed on a spiral layout.
Waffle chart
10×10 grid where each cell = 1% of total — ideal for 'X in every 100' proportional storytelling.
Icicle / partition
Two-level rectangular partition: parent categories across the top, child items within each column — encodes both parent share and within-parent composition. Options: show/hide cell labels, and show % of total instead of the raw value.
100% stacked bars
Every bar totals 100% and is divided into proportional segments — ideal for comparing compositional mix across categories (market share, budget allocation, survey breakdown). Options: rotate labels and toggle per-segment % labels.

Trend

Ensemble (common estimate)
One best estimate from many sources. Bind a label column (e.g. year), a provider/series column, and a value column: the chart draws each provider as a thin, muted line and the median of the providers toggled on as a bold consensus line — the product is the common estimate, not a vendor comparison. A translucent agreement band spans the providers' range (a tight band means high confidence); an optional reference series (e.g. AgCensus) draws as hollow squares for context and never joins the estimate. Click the provider chips under the chart to include/exclude sources — the median recomputes live, and any map on the same ensemble channel re-colors with it. The View's on-canvas Download data button exports exactly that selection — the providers left on plus the common estimate — as a file. An ⓘ Sources button opens a provenance popover: how many providers are selected, how many points have every one of them reporting, each provider's own point count (struck through when excluded), and the reference series' point count. Works identically in exports.
Line / area
Series over time or ordered categories; optional area fill, smooth (curved) lines, show/hide the per-point markers, an optional dashed moving-average trend overlay (configurable window), and a separate trend/forecast line — choose linear regression, Holt's exponential smoothing (tracks recent moves instead of just the overall slope), or seasonal Holt-Winters (adds a repeating seasonal pattern on top of the level/trend, e.g. a recurring quarterly spike — needs at least two full seasons of real data or it falls back to plain Holt) — that can extrapolate a configurable number of periods past the last data point.
Stacked area
Cumulative bands stacked on one baseline; great for volume trends. Options: smooth curve, show legend.
Bar + line
Dual-axis combo chart: bars on the left scale, line on the right. Options: a linear/Holt/Holt-Winters trend line on the line series, with an optional forecast tail that widens the chart to project past the real data.
Slope chart
Before/after per category: green line = rise, red = fall.
Step chart
Right-angle horizontal-then-vertical transitions — ideal for step-function or tier data.
Bump chart
Rank positions across periods; crossing lines show competitive overtaking. Options: show/hide the rank number inside each dot.
Stream graph
Centered stacked ribbons with a flowing organic shape — evolving volume or share. Options: show/hide the legend, and adjustable band opacity.
Candlestick / OHLC
Open-High-Low-Close bars for time-period ranges, price data, or performance spread.
Timeline / milestones
Events alternating above/below a horizontal baseline — product roadmaps, releases, project milestones.
Area range / band
Shaded band between upper and lower bounds with an optional centre line — confidence intervals, forecast corridors, min/max ranges.

Flow

Sankey (flow)
Flow ribbons from source nodes to destination nodes; width ∝ value.
Chord / wheel
Circular dependency diagram; arcs connect related nodes. Options: value format, and show/hide arc labels for a denser diagram.
Network / topology
Radial node-link diagram; node size ∝ total flow volume. Options: value format, and show/hide node labels for a denser graph.

Single value

KPI tile
Big-number callout with optional sparkline (line/bar/area), delta/compare-to, subtitle, click-through to another dashboard, and an Aggregation picker (Sum / Average / Median / Min / Max / 90th / 95th percentile / Std deviation / Variance / Range / Z-score / Correlation) that recomputes the tile from every row the bound query returns instead of only the first row — handy for binding straight to a detail query without a separate aggregate SQL statement. Correlation is the one two-column option: it reuses the Compare to section's Compare column as its second series and shows the Pearson correlation coefficient (-1..1) between it and the Value column. The Compare to section's Period column field is a one-column alternative to Compare column: pick a date/period column from the same query and the tile auto-splits its rows chronologically into two halves, showing the current half's total (per this KPI's Aggregation) against the prior half as the delta — a real period-over-period comparison ("Revenue this quarter vs last quarter") with no second column or hand-built query needed. By default the split is an even chronological 50/50; an optional Split point field lets you type an explicit boundary value instead (e.g. a date) so "prior" and "current" land exactly where you want rather than at the row-count midpoint. Every KPI tile is clickable in the exported dashboard and the Viewer: set a Click-through URL to jump to another dashboard, or leave it unset and the tile opens the shared Detail drawer instead, listing the rows behind its bound query — no tile is ever a dead number.
Gauge
Arc for a single value vs a configurable max, with a value format and red/amber/green quality-zone thresholds (like Bullet chart).
Bullet chart
KPI vs target with red/amber/green quality-zone bands.

Distribution

Scatter / bubble
X/Y dots; bind a third column to set bubble radius. Optional value format + a least-squares trend line.
Heatmap (pivot)
Color-encoded matrix; row × column cross-tabulation.
Calendar heatmap
GitHub-style day grid; cells colored by daily value. Requires a YYYY-MM-DD date column. Options: cell color, week start (Monday/Sunday).
Box plot
Five-number summary (min/Q1/median/Q3/max) per category.
Dot plot
Sorted dots on a horizontal axis; optional second column for two-group comparison.
Beeswarm plot
Individual points jittered along one axis; optional category groups.
Histogram
Auto-bins a numeric column into equal-width buckets to show frequency distribution.
Violin plot
KDE-based symmetric silhouette per category showing the full value distribution shape.
Ridgeline plot
Horizontally stacked KDE density curves per category with configurable overlap (the joy plot) — compare distribution shapes across many groups in a single compact view.

Detail

Table
Sortable, filterable grid showing all columns from the bound data access. Options: row limit (cap rows shown), a grand-total row (sums numeric columns over the currently visible rows), paging (rows per page, with Prev/Next), a freeze-header scroll mode for tall tables, and a compact row-density setting.

Content

Text / annotation
Markdown View: headings, bold, italic, code, lists — no data binding needed.
💡

Simple mode shows only the 15 most universally understood chart types. Switch to Advanced mode (⋯ More → Simple mode off) to unlock all 54 types plus specialist annotation tools.

Data sources & data accesses

Every chart View is bound to a data access (DA) — a named query. The Data panel (left pane) lists everything you can build from, in four groups: This dashboard's datasets (the queries the spec owns), Datasets (the workspace's shared catalog), Views (your saved charts), and — in Advanced mode, once you've authored one — My queries at the bottom. (The old "Samples" group of built-in demo queries is gone: sample content comes only via sample packs now, installed from Settings, so there's one source of truth.)

The This dashboard's datasets group collapses by default once it gets long (more than six cards), so the pane leads with an overview instead of a wall of cards — click a group's header to expand or collapse it any time, and your choice is remembered from then on. Each group also carries its own small glyph next to its name (a cube for this dashboard's own datasets, a database for the shared workspace catalog, a trend line for saved Views, and a code bracket for your own authored queries), so the pane is scannable by "what kind of thing is this" at a glance.

Select a View on the canvas and the Data panel shows you which dataset it reads from — that dataset's card is ringed in the list, and the same happens when you select a KPI. If the card's group is collapsed, or it's scrolled out of sight, the pane opens the group and brings the card into view; select a View with no query bound to it (an annotation, say) and nothing is highlighted at all.

Using catalog queries

Authoring new data sources (Advanced)

In the Data panel's header, click + New ▾ → Dashboard-only query… to open the data-source builder. (The + on the This dashboard's datasets group header is the quick path: it drops a blank query straight into the Inspector's editor instead.) Supported types:

Browser-native connectors: no backend required

Two source types query a file hosted anywhere over plain HTTP — S3, any static host — entirely inside your browser, with no proxy, no saved credentials, and no server connection. Both intercept the query engine's disk reads and turn them into HTTP Range Requests, so they only transfer the bytes a query actually touches. Both are flagged with a small "Browser-only" badge on their source-type card in the New Source builder, and a failed Test connection surfaces a plain-English hint (CORS/Range support, a slow/unreachable host, a 404) instead of a raw browser error. Pick whichever fits your workload:

DuckDB (remote file):

SQLite (remote .sqlite):

Both connectors run genuinely live everywhere: the builder itself (Test connection, Run live, the live-preview iframe), the offline sample preview used while you're building, and — a downloaded/deployed dashboard .html export queries the real file directly too, no server involved (the export bundles the small connector façade automatically whenever a dashboard uses one).

Snowflake connector

The Snowflake source type queries a live warehouse directly from the browser via Snowflake's SQL API — no backend or proxy, but unlike the file connectors above it's credential-based and flagged with a "Needs token" badge instead of "Browser-only". Two things to set up before it will work:

Fill in Account identifier (e.g. xy12345.us-east-1), Warehouse/Database/Schema and an optional Role, write a Query, then click Test connection & detect columns — it runs SELECT 1 to validate everything and, once you have a real query, detects output columns from the live result. The Data preview's Run live button queries the warehouse the same way.

Databricks connector

The Databricks source type queries a live SQL warehouse directly from the browser via Databricks' Statement Execution API — no backend or proxy, same credential-based shape as the Snowflake connector above and flagged with the same "Needs token" badge. Two things to set up before it will work:

Fill in the Workspace host (e.g. dbc-a1b2c3d4-e5f6.cloud.databricks.com, no protocol), the SQL warehouse id (from the warehouse's Connection details), and optionally a Catalog/Schema, write a Query, then click Test connection & detect columns — it runs SELECT 1 to validate everything and, once you have a real query, detects output columns from the live result. The Data preview's Run live button queries the warehouse the same way; statements that start out PENDING/RUNNING are polled automatically.

BigQuery connector

The BigQuery source type queries a live dataset directly from the browser via Google's jobs.query REST API — no backend or proxy. It's credential-based like Snowflake/Databricks above, flagged with the same "Needs token" badge, but Google's API already sends permissive CORS headers for this endpoint, so there's no admin allow-listing step — the token itself is the only gate.

Fill in the Project id (e.g. my-analytics-project) and optionally a job Location (e.g. US, needed for datasets outside the default region) and a Default dataset (so unqualified table names resolve against it), write a Query, then click Test connection & detect columns — it runs SELECT 1 to validate the project/token and, once you have a real query, detects output columns from the live result. The Data preview's Run live button queries the dataset the same way; jobs that don't complete immediately are polled automatically.

Generic SQL/HTTP connector

The Generic SQL/HTTP source type is the escape hatch: it POSTs (or GETs) a SQL string to any JSON API you point it at — an in-house query service, a serverless function, or a provider not yet covered by a named connector — straight from the browser, no backend or proxy. Flagged with a "Needs endpoint" badge (not "Needs token" — auth is optional and entirely up to your endpoint).

Live after export, credentials prompted at open

Like DuckDB/SQLite, the four credential-based connectors above (Snowflake, Databricks, BigQuery, Generic SQL/HTTP) query live from an exported/deployed .html too — but their secret is never baked into the exported file:

Workspace connections: every connector the wizard offers

The Connections section manages saved, credentialed connections that workspace Datasets query through. (Every password-style field in the app — sign-in, here, the backend wizard, Admin's Add-user form, the provision-secret prompt — has an eye toggle to reveal what you typed before saving.)

A connection is reusable: save it once and any number of datasets read through it — unlike the dashboard-only data accesses above, which belong to the one dashboard that declares them. Six connectors can be used either way, so Snowflake, Databricks, BigQuery, DuckDB (remote file), SQLite (remote .sqlite) and Generic SQL / HTTP are described in their own sections above and are also on this list — same backend, saved for the whole workspace instead of one dashboard.

+ New in the Connections section opens a picker with all of these, in this order. Three carry a workspace-capable badge: those can also host the whole workspace, not just answer queries (see Choosing a workspace backend below).

The Local (this browser) store is deliberately not on that list: it is where a workspace lives, not somewhere a dataset connects out to.

Workspace connections: PostgreSQL (PostgREST)

The PostgreSQL (PostgREST) adapter connects to any Postgres exposed through a PostgREST deployment — self-hosted or managed — straight from the browser:

Datasets on this connection are table-based, like Supabase: a table or view name plus an optional raw PostgREST query string (select=region,total&order=total.desc&limit=200) — with {{parameters}} allowed in both, so template variables flow into filters like region=eq.{{region}} at run time.

Connection-bound datasets are live-after-export too

A dataset built on a saved Connection — any of the connectors listed above — follows the same contract:

Workspace connections: Amazon Redshift

The Amazon Redshift adapter queries a provisioned cluster or a Serverless workgroup directly from the browser via the Redshift Data API — no backend or proxy:

Browse a connection's schema

For Snowflake, Databricks, BigQuery, Amazon Redshift, PostgreSQL (PostgREST), DuckDB and SQLite connections, the Connections editor has a Browse schema button next to Test connection: fill in credentials, click it, and every table the connection can see lists out, each expandable to its columns and types (a filter box narrows long lists by name).

The same schema browser is one click away while building a dataset, not just when editing the connection: the Dataset editor's "Browse schema" button (shown for the same set of connections, once one is picked) opens the identical table/column tree — but here every table and column is clickable. Picking a table fills the Table field on a PostgreSQL/PostgREST-shaped dataset; picking a table or column drops its name straight into the SQL query at the cursor for every other kind. No more copying names back and forth from a separate tab.

Studio's own New data source builder (the query editor behind the Data panel's + New ▾ → Dashboard-only query…) has the same button under its Query field for the credentialed kinds — Snowflake, Databricks, BigQuery, DuckDB (remote file) and SQLite (remote .sqlite). Fill in the credentials (or the file URL), click Browse schema, and click any table or column to insert its name into the SQL at the cursor. The built-in sample-engine SQL kind and the Generic SQL/HTTP kind have no catalog to introspect, so they don't show the button.

The same builder also runs a live sanity check over the SQL as you type: an unclosed string literal or quoted identifier, unbalanced parentheses, a statement that doesn't start with SELECT/WITH, or a declared column chip the query never mentions each surface a small warning on the line under the query field (and clear the moment you fix them). It's a lightweight shape check across all the supported engines, not a full SQL parser — the Preview and Test connection buttons remain the way to prove a query actually runs.

Writing SQL: highlighting, column help, and what actually gets checked

Every SQL box in the app is a real editor rather than a plain box — the Dataset editor's SQL field, all seven per-adapter query fields in the New data source builder (the built-in SQL engine, DuckDB, SQLite, Snowflake, Databricks, BigQuery and Generic SQL/HTTP), and the Jobs Custom-SQL step. Keywords, strings, numbers, comments and {{parameter}} placeholders are coloured as you type, in both themes and every palette.

Each surface offers what it honestly knows, and no more. The New data source builder's boxes offer the column chips you've declared or detected, whatever Browse schema has loaded, and the query's own parameters — a brand-new source with nothing tested and nothing browsed gets keywords and functions and invents nothing, because those fields are filled in before a connection exists. The Jobs SQL step is the opposite case: it runs against the rows your pipeline has produced so far, loaded into a DuckDB table named t, so it offers exactly those incoming columns and that one table, and keeps up when you change a step above it — and because it knows that table's shape exactly, t. narrows to it. Qualified completion needs a table that can say what it holds, which in practice means one Browse schema has loaded, or the Jobs step's t.

Workspace connections: Google Sheets

The Google Sheets adapter charts a sheet shared as "anyone with the link can view" straight from the browser — no OAuth, no API key:

Private sheets

Fill in the optional OAuth access token field — a short-lived Google OAuth 2.0 token scoped to spreadsheets.readonly (e.g. from the OAuth Playground), the same "paste a token, never a key file" shape as BigQuery.

Workspace connections: CSV / JSON files

The CSV / JSON file adapter is the fastest way from a file on disk to a chart: add a file connection (nothing to configure), create a dataset on it, and drop a .csv, .tsv, .json, or .xlsx onto the editor's drop zone (an Excel file's first worksheet is read — values only, dates as Excel serial numbers).

Calculated columns

Every data source has a Calculated columns section (Advanced mode): give a Name and a Formula that references other output columns in square brackets, with + - * / ( ) supported. Examples:

A bad reference — unknown column, divide-by-zero, malformed syntax — shows an inline error naming the problem instead of failing silently. Once valid, the calculated column is a real, bindable column everywhere a View or KPI picks columns from this source, computed live in the offline preview — and for the six direct-query connectors (DuckDB, SQLite, Snowflake, Databricks, BigQuery, Generic SQL/HTTP) it's appended to the live query result in exported/deployed dashboards the same way.

Data source freshness

Any live-capable data access (DuckDB, SQLite, Snowflake, Databricks, BigQuery, Generic SQL/HTTP, or a dataset bound to a workspace connection) shows a "Last verified live …" / "Never verified live" badge in the Data preview:

Joins and compound DAs

A Compound data access — either a join (left/right DA + key columns) or a union (stack rows from N DAs) — is computed in the builder over the member DAs' rows. The builder no longer authors new ones: joins and unions belong in Jobs (left rail), so the Data panel's old ⧈ Join entry is gone. Any dashboard that already has a compound DA still renders it and still edits it in the Inspector.

Dataset lineage

The Datasets catalog badges each row with "↪ N dashboards" when one or more saved dashboards reference it — hover the badge for the list of names. It's a blast-radius view: before deleting a dataset, you can see what depends on it. Deleting one that's in use warns you which dashboards reference it — they don't break, but they fall back to the self-contained copy of the query that was saved into them the last time they linked to it, rather than continuing to follow live edits to the dataset.

Filtering datasets and connections

The Datasets list narrows by four cross-cutting pill strips at once, plus the search box:

Pills in the same strip are OR'd; different strips are AND'd; a "Clear" chip resets everything. The Connections list has the same adapter and tag pills — give connections Tags (comma-separated, in the wizard) to slice a growing catalog by "prod" vs. "staging" without a new connection per environment.

Select multiple / bulk actions on datasets, connections, jobs & the Repository

Click Select on the Datasets, Connections or Jobs page to enter multi-select mode — a checkbox appears on every tile/row, and tapping anywhere on a card or row toggles its selection instead of opening it. A bar above the list shows how many are selected with Select all (everything the current search/filters show) / Clear, a Move to folder… button that files the whole selection in one go (the same folder browser every Folder field uses — pick a folder, create a nested one inline, or choose "No folder" to un-file), and a Delete button that removes every selected item after a confirmation (see Undo below; datasets referenced by a saved dashboard, connections referenced by a dataset, are called out by count in that confirmation, same as deleting one individually — deleting jobs in bulk keeps their output datasets, same as deleting one). Click Select again (now labeled Cancel) to leave select mode. The same pattern first shipped on Dashboards. Repository — the searchable catalog across every object kind — has its own Select button too: a selection can mix dashboards, datasets, connections, Views and jobs together; one Move-to-folder choice refiles them all, and the delete confirmation names how many of each kind you're about to remove. The Views page has the same Select button and bulk bar — select any number of saved Views, then move them to a folder or delete them together.

Layout. Every catalog page opens as the compact list — the densest way to scan a lot of items, and the shape the search, sort and filter controls above it are built around. The Tile view button in the page header swaps it for a grid of cards (dashboards show their thumbnail there), and your choice is remembered per section on this device from then on. Dashboards used to be the one page that opened as tiles; all six now start the same way, and Home still greets you with dashboard thumbnails either way.

Sorting. Every catalog page — Dashboards, Views, Datasets, Connections, Jobs and the Repository — has a sort control beside the layout toggle: Newest first (the default; Dashboards labels that same option Last updated), Oldest first, Name A–Z / Z–A, plus per-section extras (Dashboards by workbook or folder, Datasets by adapter or connection, Connections by adapter, Views by chart type, Jobs by last run — the Repository has none). Your choice sticks per section on this device. On Datasets, Connections and Views a pinned item stays at the top whatever the sort; a dashboard's pin sends it to Home rather than to the top of this list, and Jobs and the Repository have no pin at all.

Searching. Every catalog page searches the same way. Type as many words as you like: every one has to turn up somewhere on the item — all of them, not any of them — in any order and across any field, so crops 2024 finds a dataset named "Cover crops" filed in the "2024" folder, even though those two words never sit next to each other. Wrap words in "double quotes" when you do mean the exact phrase: they then have to sit together, though "together" is measured across the whole item rather than within one field, so "crops 2024" also matches where the name ends in "crops" and the folder beside it begins "2024". Case never matters. An empty box matches everything, so emptying the search is how you get the whole list back. The Clear chip above the list means show everything: it drops the facet pills and empties the search box, and it appears whenever either one is narrowing the list. Five pages have a Clear chip — Dashboards, Views, Datasets, Connections and Jobs; the Repository is the exception, and Un-picking a pill below has the way back there.

What counts as a word. Spaces are the only separator, and everything else you type stays part of the word it is touching. That is what lets you search for a name that contains punctuation — q2.2024 finds "Revenue q2.2024" — but it also means a comma you added out of habit goes looking for itself: crops, 2024 hunts for the literal crops, and comes back empty on the very dataset crops 2024 finds. Quotes work the same way and only in pairs, so a single unmatched " is just another character in the word beside it — cover "crops searches for cover and for "crops, quote mark included, and finds nothing. If a search you are sure about comes back empty, a stray comma or an unclosed quote is the usual reason.

What each page searches. Every page searches the item's name and its folder. On top of that: Dashboards add the description and, as a fallback when nothing else matches, the column names its charts are bound to (the matching column is named right on the card); Views add the chart type; Datasets add the description, the owner, its tags, its column names and the query text (or the table or collection it points at), plus the name of the connection it reads; Connections add the adapter, its tags and the rest of its settings — never a password or token; Jobs add the source dataset and the output dataset; and the Repository adds the one-line summary each row shows under its name.

…and every other search box too. The same rules run behind every search field in the app, not just the catalog pages: the builder's Data panel (all three of its groups — Datasets, Views and My queries), the Inspector's search, the chart-type gallery, the command palette (⌘K), the What's-new feed, the folder picker, the Quick Views pane, the View Builder's datasets pane and its value filter, the auto-build set list, the Open a dashboard picker and the "add to dashboard" picker that shares its list, and a connection's schema browser. Words in any order, quotes for an exact phrase, case-insensitive — wherever you type. The command palette layers its own ranking on top (a command whose name starts with what you typed comes first), and the What's-new feed highlights each word it matched. Two boxes work differently, both deliberately: a table View's own Filter rows box matches one literal string across the row's cells — so crops 2024 finds a row only where those two words sit side by side — because that table travels inside every exported dashboard and carries its own self-contained rules rather than the app's; and this Help page's own search box is part of the page you are reading rather than the app.

Filtering with pills. Above each list sits a row of filter pills, each carrying a count beside its label. Picking none of a facet's pills means all of them, so the pills only ever narrow — and pills are listed in the order you read them, alphabetically by their label and numerically where numbers appear (so "Q2" comes before "Q10"). Two strips keep an order of their own instead: Dashboards' workbook pills stay newest-first, and the Repository's type pills sit in the fixed order the app declares them in.

What the number on a pill counts. Every pill has one, and it counts everything on the page that the pill covers — not what you can currently see. The number is worked out before the search box and before every other pill, its own strip included, so it never moves as you filter: narrow a list down to two rows and a pill above them can still read 40. That is the useful number, because it tells you what picking that pill would give you rather than what you already have. The counts also overlap wherever a facet takes more than one value, so a strip's numbers can add up to more than the list itself — a dataset tagged both #finance and #eu is counted under both tag pills. The pills that mean everything — All on Dashboards' workbooks and on the Repository's types, All folders on a Folders strip — carry the whole list's count, which is again what picking them gives you.

When a pill goes away. On most strips a pill exists only while an item sits behind it — the adapter, connection, tag, dataset-type, chart-type and folder pills are built from the items themselves, so the last one to leave takes its pill with it, and a pill never reads zero. Three strips keep a pill you can empty out, and each of them earns it: Unfiled stays at the end of a Folders strip even when everything is filed; on Dashboards, a workbook you made keeps its pill after the last dashboard leaves it — that pill is how you file one back in — and so does that strip's own Unfiled; and the Repository always shows all five type pills, so an empty workspace shows five zeros rather than an empty strip. Either way, a filter can never keep narrowing the list from something you can no longer pick: when the last item behind a pill you had ticked goes away, the app drops that filter for you and puts the list back.

Which pills take more than one. Some facets are multi-select — tick two pills and the list shows anything matching either: Datasets by adapter, connection, type or tag; Connections by adapter or tag; Views by chart type. One pill at a time: the Folders strip, on each page that has one; Dashboards by workbook, the strip that also offers Sample packs and Unfiled; and the Repository by type, one pill per kind of row it lists.

How the strips combine. Within one strip the pills are alternatives: tick a second pill on a multi-select strip and the list grows, because a row need only match one of them — and a row carrying several values of that facet needs only one of its own values ticked, so a dataset tagged #finance and #eu survives a pick of either tag. Between strips it is the other way round: every strip you have picked from has to be satisfied at once, and the search box counts as one more of them — adapter Postgres, tag #eu and the word revenue together show only the rows that answer all three. A strip you have picked nothing in narrows nothing, which is what keeps the pills a narrowing tool rather than a mode; it is also why a combination can legitimately come back empty while every pill above it still carries its own full count.

What a pill says. Each pill is labelled with the app's own name for the thing it narrows to, so the strip reads the way the list under it does. Adapter pills (Datasets and Connections) carry the adapter's name and its colour dot — the same names the connection wizard offers. Connection pills, on Datasets, carry the connection's own name; on both of the Datasets strips, a dataset with no connection behind it lands under No connection. Tag pills keep the hash you write a tag with, so a tagged item filters under #finance. Datasets by type has one pill per kind of dataset: SQL query, Table, Collection, File and Sheet. Views by chart type prints the chart's own name from the gallery — Bar chart, Line / area — with one label the gallery does not hold: a KPI tile's pill reads KPI. The Repository's type pills are the kinds of row it lists: Dashboards, Datasets, Connections, Views and Jobs. Dashboards by workbook opens on All, then Sample packs whenever an installed pack brought dashboards of its own, then one pill per workbook you have made, and Unfiled for the rest.

Un-picking a pill. The multi-select facets toggle — click a pill you have already ticked and it un-ticks. The single-select strips do not: clicking the pill you are already on leaves you on it, so each of those strips opens with a pill that means everything — All on Dashboards' workbooks and on the Repository's types, All folders on a Folders strip. That pill is the way back, and on the Repository it is the only one: it is the one catalog page with no Clear chip, so empty its search box yourself.

The Folders strip. Single-select — All folders, one pill per folder in use, and Unfiled for everything filed nowhere — and it only appears once something has actually been filed. Five pages have one: Dashboards, Views, Datasets, Connections and Jobs. The Repository is the exception: it groups its rows into a nested folder tree instead, so there is no strip to pick from.

Changed your mind? Undo. Every Delete — bulk or a single row — shows its toast with an Undo button for a few seconds, and one click restores everything just removed, under the same ids, exactly as it was. That now covers every destructive button in the app, including three that used to only ask once and forget: the View Builder's "Delete dataset" (which also brings back the shelves/filters/calculations you had in flight on it, and re-selects it if you were building on it), the Quick Views sidebar's delete (which reopens the View if it was the one you had open), and Remove on a sample pack. The restore is workspace-backend safe: an undone delete propagates as a re-creation, so the items come back on your other devices too.

Filing a dataset, connection, job or View into a Folder

Datasets, connections, jobs, saved Views, and (via Repository quick-edit) dashboards all have a Folder field — one home for the item (e.g. "Finance"), distinct from Tags (which can be many). Three ways to fill it:

Once anything is filed, the Datasets / Connections / Jobs / saved-Views lists grow a folder chip strip (All folders / each folder / Unfiled) above their other filters, and each row wears a small folder badge.

Every Datasets, Connections and Jobs row carries its own controls

The catalog pages aren't only lists to scan — most of the day's work happens on the row itself, without opening anything. Each row ends in its own cluster of controls; clicking anywhere else on the row opens the item in its editor, so the controls never fire by accident. They're the same on the compact list and on a Tile view card.

Views — browse your saved charts

The Views catalog: chart-type icons, folder badges, and per-row actions
The Views catalog

The Views section is the browse/manage catalog for every View you've saved — a reusable chart, KPI, pivot, or map. The builders (Quick Views and the View Builder) are where you make and edit one; Views is where you find it again. Search by name, narrow by chart type or Folder, and flip between the compact list and Tile view (remembered per device). Each row's icon previews its actual chart type — the same themed thumbnail art the chart-type picker uses.

Every row offers:

+ New ▾ offers both builders — New View (the View Builder) and New Quick View (the fast one-chart path).

Repository — search the whole workspace

Repository: the kind chip strip and the nested folder tree over every workspace object
Repository: every object, one tree

The Repository section is one searchable view of every object in your workspace — dashboards, datasets, connections, Views, and jobs — with a chip strip to narrow to one kind (each with a running count). It's the fastest way to find one specific thing once a workspace has grown past a glance.

Browse — a real folder tree

Act — open, edit, file, create

Saved views

Once a search and/or adapter/connection/type/tag pill selection narrows the Datasets or Connections list to something worth returning to, a "+ Save view" box appears next to the filter chips — name it and it becomes a chip of its own. Click that chip later to instantly restore the exact same search text and filters; hover it for a small trash button to delete it. Saved views live in the same workspace-settings store as Dashboards' workbooks, so they sync across devices along with the rest of your workspace.

Marking a dashboard, connection, dataset, View, or job private

A lock toggle on every Dashboards, Connections, Datasets, and Jobs row, and every saved View in Quick Views' list marks that item private — it stays visible to you and to admin accounts, but disappears from every other signed-in account's catalogs (and, for connections, from the connection picker other people see when authoring a dataset, and for datasets, from the source/join/union dataset pickers when authoring a job). This is UX-level gating, the same honesty as the rest of sign-in — an admin account (or local/no-auth mode with no sign-in configured) always sees everything. All five saved-object types now have the toggle.

Admin & backend setup

These topics are for the person who administers a shared workspace — wiring up a real backend, provisioning teammates, and turning on database-enforced per-user security. Everyday building never needs any of it; a local workspace works with no setup at all.

Choosing a workspace backend

A workspace backend is where your whole workspace — dashboards, datasets, connections, jobs, saved Views and settings — lives, and whether it travels to other devices and teammates. All four options query the same way and carry the same objects; they differ in where the data lives, whether it syncs, and how strongly per-user privacy is enforced. Set or switch it under Settings → Workspace backend.

BackendWhere data livesSyncs across devicesPer-user accounts & privacySetup
Local default This browser only. No — stays on this device. Local sign-in only (usernames on this device); private/public flags are UX-level. None — works instantly, nothing to configure.
Turso Turso (libSQL / SQLite) in the cloud. Yes — every device pointed at it shares one workspace. Shared credential (one URL + token); accounts and private flags are UX-level, not database-enforced. Paste the database URL + auth token; it creates its own schema from the browser (no SQL to run).
Supabase Postgres (via its REST API). Yes. Strongest. Real per-user accounts (Supabase Auth / GoTrue) and optional database-enforced Row-Level Security — the only backend where private truly means private at the database, not just hidden in the UI. Add users from the Admin console. A one-time SQL script pasted into Supabase; an optional polecat-admin Edge Function unlocks in-app go-live + admin-create (see below).
Firebase Cloud Firestore (document store). Yes. Enforced by your own Firestore security rules, configured in the Firebase console (not from inside Studio). Configure Firestore + security rules; collections appear on first write.

The picker shows three more cards, greyed out and badged Future: PostgreSQL — your own Postgres, exposed over REST (PostgREST); Cloudflare D1 — serverless SQLite at the edge, via a Worker API; and MongoDB Atlas — hosted MongoDB through the Atlas Data API. Each one could host the whole catalog over a REST surface, none has an adapter yet, and they are listed so you can see where the roster is headed rather than wonder whether you missed a setting. They cannot be selected.

The first of the three is worth a sentence, because the page can otherwise look like it contradicts itself: PostgreSQL is greyed here while PostgreSQL (PostgREST) sits in the connector list above as something you can use today — and both are right. A PostgREST connection answers dataset queries. Hosting the workspace itself — the app's own catalog, its schema migrations, the sync protocol — is a separate capability, and only the backends in the table above have it. The same split explains the workspace-capable badge on three of the thirteen connectors.

Short version: stay on Local for a private, single-device workspace; pick Turso for the simplest shared workspace across your own devices or a trusted team; pick Supabase when you need real accounts and database-enforced per-user privacy; pick Firebase if you already run Firestore and manage access through its security rules. The rest of this section covers the Supabase-specific admin flow in detail.

Standing up a Supabase project (the step before any SQL)

Every other Supabase topic below starts one step too late — at “paste this script”. This is the step before it: creating the project. Supabase's create-project screen asks three Security questions and two permanent ones, and the answers are not obvious — one of them is the opposite of Supabase's own recommendation. Each answer below is derived from the SQL this app actually ships, and is named so you can check it yourself.

The three Security toggles

ToggleAnswerWhy
Enable Data API ON — required. The Supabase adapter is a PostgREST client — the Data API is the only door it knocks on. With it off, the project has no HTTP surface and the connect wizard cannot reach it at all, whatever else you set.
Automatically expose new tables to the Data API OFF — as Supabase recommends. This one used to be the counter-intuitive answer on this page, and it no longer is. tools/supabase-deploy.sql now carries its own privileges (its § 6c), so the recommended, tighter setting is finally the correct one too. Until 2026-08-08 that file contained no GRANT statements and leaned entirely on the project's default privileges — so turning this toggle off left you tables with row-level security and the right policies but no table-level grant to anon/ authenticated, and PostgREST refused every request with an error that looked nothing like its cause. If § 6c is ever removed, this answer goes back to being the looser one, and this page has to change with it.
Enable automatic Row Level Security on new tables ON. Belt and braces. The deploy script already enables RLS and installs a policy on every workspace table itself, so this changes nothing for the tables it creates — it protects anything created outside it later. Note that with Supabase's newer publishable keys a table with RLS on and no policy returns zero rows over the Data API rather than erroring, so RLS-on is the app's normal working state, not a locked-down mode you switch out of.

The two answers you can only get right at creation

Then: which SQL file to run

The repository ships three Supabase SQL files and they are not interchangeable. For a brand-new project there is one answer:

FileWhenWhat it is
tools/supabase-deploy.sql A fresh environment — this is the one. The superset, run top-to-bottom and bare (no begin/rollback wrapper): workspace tables, the verified authenticated-only RLS posture, the activity and feedback log tables, the first-admin step and a verify block. Idempotent — safe to re-run.
tools/supabase-rls-real.sql Re-tightening a project whose tables already exist. The security posture alone — the subset of the file above. Nothing to run on a fresh project that has already had the deploy script.
tools/supabase-bootstrap.sql Historical. The original allow-all demo posture, kept for reference. Not for new environments — it deliberately installs no policies.

Dev and stage run the same posture as production — the real one. An environment whose security posture differs from prod cannot test the thing most likely to break, so “it's only dev” is never a reason to reach for the allow-all file.

You can also get that same script without leaving the app. Point Settings → Workspace backend → Connect at a blank Supabase project and the wizard hands you a script to paste into the SQL editor — and since v904 that script is the deploy file above: the same tables, the same authenticated-only RLS posture, the same grants, with § 7 pre-filled for the account you are signed in as whenever the app can resolve its Supabase Auth uid. (Before v904 the wizard generated tables and a comment reading “then enable Row-Level Security policies appropriate to your project”, so the one path the UI actually offered left the database wide open. Both paths now install the same thing, and a dev-gate check compares them on every run.) Because that script ends with the database closed to anonymous callers, the wizard asks for this connection's Supabase Auth email and password before it will connect — the anonymous key alone can no longer read or write the workspace.

The Auth fields are required, not optional

On a workspace set up by that script, Supabase Auth email and password are what make the connection work at all. Every policy is granted to authenticated callers, so a connection without them signs in as anon, auth.uid() is NULL, and each policy declines by returning no rows — the workspace reads as empty rather than refused, which looks exactly like a database that was never provisioned. Since v907 the app names that state instead of leaving you to guess: the connect wizard says the workspace enforces per-user security and offers a step back to the credentials, and an already-saved connection in that state reports it on the Settings backend card and keeps working from this browser's local copy — it will never adopt the emptiness over your own work. Only a legacy allow-all database still works on the anon key alone.

Two things about those fields that surprise people, and neither is a fault:

The two steps the script cannot do for you

Both are once per environment, and both are spelled out in the script's own numbered sections:

Things that only bite later

The environment topology

The databases mirror the app's own dev → stage → main delivery pipeline — a separate project per stage, each with its own project URL and database password, so an experiment can never be run against the workspace that real people use:

The posture test only ever builds throwaway schemas of its own and never touches public, whichever project it is pointed at.

How syncing works (and what the rail indicator means)

With a backend connected there is nothing to "sync" by hand — every change (saving a View, editing a dashboard, adding a dataset…) mirrors up automatically a moment later. The rail indicator (Manage group) shows the live state:

“Read-only — created by a newer version”. Every workspace records the schema version it was built at, and the app checks it whenever it connects, refreshes, or quietly re-reads the backend — and whenever a tab you left open becomes visible again, or a device comes back online. Those last two matter because the quiet re-read deliberately skips itself while you have unsaved changes waiting (adopting the backend copy at that moment would overwrite them), so the tab most likely to be out of date was the one that never looked. The resume check reads only the single line that records the version, downloads nothing else, and the save that waking a tab sets off waits for it rather than racing it. If the workspace is newer than the app, the app stops writing to it and says so with a banner: an older build saves a whole snapshot of the tables it knows about, so one push from a stale tab could quietly drop whatever the newer version added. Reading is unaffected — the workspace opens and works normally, and anything you change stays in this browser. Reload the page to pick up the newer app (and if the banner keeps coming back, use Settings → App → Hard reset to clear a stuck offline copy); once the versions line up, the changes you made in the meantime push up on the next Refresh.

Upgrading an older workspace. The opposite case — a workspace made by an earlier version of Analytics — is not a problem: every change to the workspace shape has only ever added to it, so an older workspace keeps working exactly as it always has. It just has nowhere to put the parts newer versions added, which is what turns up much later as a save failing on a table that isn't there. You can settle it in advance: when the versions differ that way, the Settings → Workspace backend card names both of them and offers an Upgrade workspace button. Two things are worth knowing before you press it. First, a full backup of the workspace downloads first, every time — it is not a checkbox you can turn off, and if the backup can't be written the upgrade doesn't run at all. The file is a plain JSON copy of everything the backend holds, taken immediately before anything is changed. Second, the upgrade only adds — nothing you have saved is read, moved or deleted, and it is safe to run twice.

Turso and Firebase workspaces upgrade in one click, because those backends let the app create what it needs directly. Supabase workspaces set up with the current script upgrade in one click too: that script installs a small, admin-only database function whose job is exactly this, so pressing Upgrade workspace runs the upgrade from inside the app. The card tells you which kind of database you have before you press anything. Only an administrator can run it — that check lives in the database itself, not in the browser.

A Supabase workspace created before that function existed still needs one manual run, and the card says so: your backup downloads, then Copy SQL, run it once in Supabase → SQL editor, and press I've run it — re-check. Either way the upgrade adds the missing tables and records the new version; it does not touch your Row-Level Security policies or your grants, so an upgrade can never loosen who can see the workspace.

A failed write also raises a one-time notification and puts the full error on the Settings → Workspace backend card, with a Retry now button.

One error worth knowing: a Supabase workspace provisioned before newer app versions can be missing the analyses/jobs/users tables — saving a View then fails with HTTP 404 writing analyses. The Settings card shows the one-time upgrade SQL in a copyable block: paste it into Supabase → SQL editor, run it once, then hit Retry now and the pending changes push up.

Atomic saves (Supabase). A Supabase workspace normally saves one table at a time, so a connection dropped part-way through a push can leave it half-written — the newest dashboards saved, say, but not the datasets they read. Installing one small database function makes every save a single transaction instead: it either fully lands or fully rolls back. The Settings → Workspace backend card says which state your workspace is in, and offers the one-time SQL with a Copy SQL button when it isn't atomic yet — paste it into Supabase → SQL editor and run it once. It changes no data, runs under your own database permissions, and is safe to run twice. Workspaces provisioned from now on get it as part of the bootstrap script; ones that skip it keep saving exactly as before. (Turso and Firebase workspaces were already atomic — nothing to do there.)

Sync is also hardened against a flaky network or backend: a single failed request (a rate-limit 429, a 5xx, a dropped connection) retries once on the spot before anything is reported, automatic pushes keep a minimum spacing so rapid editing can't hammer the backend into rate limits, and the Settings backend card shows a Recent sync activity log — the last several push/pull attempts with the exact error text for any that failed, so "it keeps reconnecting" always has a readable reason attached.

Syncing works in both directions on its own: besides pushing your changes up, the app quietly checks the backend every couple of minutes and whenever you return to the tab, silently refreshing the screen when a teammate or another of your devices saved something. It never overwrites edits this browser hasn't pushed yet — if anything is pending here, the check simply waits — and an empty or failed read is never adopted over real local work.

Where credentials and passwords are kept

Studio runs entirely in your browser, so it is worth being plain about what is stored where — and in what form.

Signing in with real Supabase Auth (optional)

The Supabase connect wizard has two optional fields below the Project URL and anon key: Supabase Auth email and password.

Signing in on a new device is one step. Once a workspace is connected to a Supabase backend, a teammate can sign in on a brand-new browser by entering their email and password on the sign-in screen — the app verifies those straight against the backend's own Supabase Auth (GoTrue), then adopts their account locally. No admin needs to re-add them here first, this browser doesn't need to have seen the account before, and no password is ever mirrored between devices — the backend itself is the source of truth. (Signing in with a plain username, or on a local/non-Supabase workspace, works exactly as before.)

On a connected Supabase workspace, the workspace decides who gets in. When you sign in with an email and a Supabase workspace is selected, the app now asks that workspace's own Supabase Auth first and takes its answer as final. If it says no, the copy of your password digest that happens to be mirrored on this device gets no second vote — so changing (or revoking) a password in the workspace takes effect everywhere immediately, instead of waiting for each browser's mirror to catch up. Two deliberate exceptions:

Once per browser session, you'll be asked again. Because the password isn't kept on the device, a workspace session lasts as long as the browser session does. Reloading a tab, or leaving one open, never asks; closing the browser completely and coming back does — with your email already filled in, so it's one field. That ask is also a safeguard: a browser that can no longer prove who you are would otherwise carry on as an anonymous visitor, and on a workspace with per-person privacy switched on that looks exactly like an empty workspace. The app waits for you to sign in rather than showing you nothing and syncing that nothing back. Signing out ends the workspace session too, so the next person at this browser starts from scratch.

Picking a workspace on the sign-in screen

The sign-in screen has a Workspace picker above the username field, so a teammate never has to touch connection setup at all:

Picking a workspace only points the app at it — nothing is read or written until you actually sign in, so an unauthenticated device can't disturb (or be disturbed by) the workspace's data. Admins create the access file from Settings → Workspace backend → Export access file on any connected device, or from any entry in the saved-workspace list — including on the sign-in screen, so you can define a workspace and hand someone the file without signing into it first. It contains the workspace's connection key (share it only with people who should be able to sign in), and it deliberately strips the connection's own service sign-in — each teammate authenticates as themselves.

What follows you between browsers

On a connected workspace, your content has always roamed — dashboards, Views, datasets, connections, jobs, folders, and pins live in the workspace and arrive on any device you sign into. Two more things now roam too: branding (the app name, link, and icon an admin sets) is workspace-wide — everyone who connects sees it — and your theme (color theme + light/dark) is saved on your own account and applies wherever you sign in. The two local demo accounts stay browser-local, since they have no backend identity. Your wider personal setup roams as well: Simple mode, the restore-unsaved-work opt-in, the builder's side-panes preference, sample visibility, pane sizes (Studio's side panes, the View Builder's datasets pane and chart canvas), and your tile/list layout picks for Dashboards and the Repository — all saved on your own account row and applied when you sign in elsewhere.

Invite hot links (prefilled sign-in)

For a hand-out that's even lighter than an access file, an admin can send a teammate a hot link that pre-selects the workspace and prefills their credentials, so all they do is click Sign in:

https://analytics.polecat.live/app/#ws=WORKSPACE-ID&user=EMAIL&pass=PASSWORD

ws is the workspace's picker id (the packaged Polecat workspace is polecat; local works too), and user/pass are optional — include either or both. Values must be URL-encoded if they contain characters like @ or & (an encoded @ is %40). The credentials ride the URL fragment (everything after #), which browsers never send to any server, and the app scrubs it from the address bar the moment the page loads — it won't sit in the location bar or be bookmarkable after that first load. Treat a hot link exactly like the password it contains: share it over a channel you'd trust with the password itself, and don't put one anywhere public. Links that carry a workspace this browser doesn't know prompt the recipient to pick one or import an access file instead.

Adding users when connected to Supabase (in-app account provisioning)

Once the workspace backend is Supabase, the Admin page's + Add user form gains an Email field and creates a real Supabase Auth (GoTrue) account via the public sign-up endpoint, stamping the account id onto the user's row:

Per-user provisioning defaults (first sign-in)

The Admin page's Add user (and Edit user) form carries two pickers that set an account up before its owner ever signs in: Default theme, and Sample pack — a list of every pack this build ships, so an account can arrive with whichever of the sample packs suits the work it was created for, not just one. Set either and that new account logs in ready: the app color theme switches to the one you picked, and the pack installs itself — no manual setup, no digging through Settings. This only ever runs once, the very first time the account signs in anywhere; after that it's stamped as provisioned and later logins never fight whatever the user has since changed for themselves. Leaving the theme at "Don't set" or the pack at "Don't install one" simply skips that part.

The same form also has a "Copy my current Dashboard defaults" button — click it and Studio snapshots your own Settings → Dashboard defaults (default subtitle, accent color, header logo, header background, title size, subtitle style, dashboard theme and card style), together with your stored Quick-import creativity level, and stashes the lot on the new account. That last one is worth naming because you cannot see it: its row on the Settings card is hidden for now, but the stored value is real and it travels with the snapshot like everything else. At their first sign-in, that whole "house style" applies automatically alongside the theme/pack above, same once-only rule. Clear removes a previously captured snapshot before saving.

Disable a user (without deleting them)

Every row in the Admin users list has a Disable button. Disabling an account blocks sign-in — on every device — with a clear "this account has been disabled" message, and if they're signed in somewhere right now, that session ends the next time the app loads. Nothing is deleted: the account, its role, its provisioning, and everything it owns stay exactly as they were, and Enable restores sign-in instantly. You can't disable your own signed-in account, and the last admin still able to sign in can never be disabled (there'd be nobody left to undo it). Use this instead of Remove when someone might be back — or when you want their work to stay attributed while they're away.

Force the welcome tour at next sign-in

The same Add/Edit user form has a "Show the welcome tour at their next sign-in" checkbox. Normally the welcome tour appears only the very first time a browser visits the app — so if someone's device has already seen it (or you're re-testing an account), a fresh sign-in shows no tour at all. Check this box and the account's very next sign-in opens the welcome tour anyway, on any device. It's one-shot: the flag resets itself the moment the tour is shown, so later sign-ins go straight in as usual. Re-check it any time you want to force it again. (Anyone can also replay the tour themselves whenever they like from the Home page's "Take the tour" card.)

Managing multiple workspaces (admin)

The Admin page's Workspaces card saves the databases this app can work in — Turso, Supabase, or Firebase — under a name, with credentials, ahead of connecting to any of them. Saving one is just remembering it for later: it does not sync, mirror, or connect anything by itself. (The card was called Backends until the two lists became one; "backend" now names only the state — Workspace backend — Local (this browser) — never a row in this list.)

It is one list. The workspaces saved here, the workspaces you save at the sign-in screen, and the entries Settings → Workspace backend manages are all the same saved list — so a workspace saved in Admin can be signed into from the Workspace picker, and a workspace someone saved (or imported from an access file) at sign-in can be assigned to a user here without re-typing its credentials. Removing an entry in either place removes it in both; the database itself is never touched. A workspace you started but never finished configuring is kept and still editable here — it carries a not configured badge and is simply not offered at sign-in, since it cannot yet say where it points. The workspaces packaged with the app are offered at sign-in as well, but are not managed on this card: they ship with the build.

Once at least one workspace is saved, the Add/Edit user form (same "Per-user provisioning defaults" area above) also gains an Assigned workspace picker naming which saved workspace that account belongs to — shown back on their row in the Users list too (→ Workspace name).

The assignment is real: it connects at sign-in. Assigning a workspace stores its connection details with the account, so they travel wherever the account signs in. On a brand-new device (nothing user-made stored locally) the app connects to the assigned workspace automatically — no setup, nothing to type. On a device that already carries local work, the app asks first, since switching adopts the workspace and replaces what's stored locally; declining is remembered per workspace, so sign-in never nags. And if it reads back empty — the signature of a locked-down (per-user security) database that needs its own sign-in — the app refuses to adopt it over your local data and points you at the sign-in screen's Workspace picker instead, which handles that case properly.

Going live with real per-user security (Supabase)

The private/public flag on every object is UX-level by default — hidden from other accounts in the app, but the Supabase backend still stores everything under one shared key. An admin can flip that to real database-enforced Row-Level Security from the Admin page's "Enable per-user security / Go live" card:

  1. One-time deploy (repo maintainer, not the app): the polecat-admin Supabase Edge Function — see tools/M7-RLS-GOLIVE-RUNBOOK.md for the exact commands.
  2. Paste its URL into the Supabase connection's Admin function URL field, and sign in as the account that should become the first admin (the Auth email/password fields).
  3. Click Go live and enter the one-time provision secret set at deploy time — used once, never stored.

Go live wipes the current workspace tables (your browser's own data is untouched), seeds you as the admin, and applies the real per-user policies — from then on, private truly means only you (and admins) can see it, enforced by the database. With the relay deployed, + Add user also switches to the more secure admin-create path automatically (no email-confirmation step); plain self-signup stays the fallback without it.

First-admin bootstrap is automatic. Go live records your own admin account for you (in the database) before it runs, so on a brand-new project it no longer stops with "This account is not an admin of this workspace" — you don't have to hand-run any SQL in the Supabase editor to make yourself the first admin. It also refreshes your Supabase Auth sign-in each time, so a session that quietly expired won't surface as "That sign-in session is no longer valid" — just click Go live (or + Add user) again. The one prerequisite the app still can't do for you is the maintainer's one-time polecat-admin function deploy above.

Exporting dashboards

Click Export ▾ in the topbar to open the export menu (it only shows while Studio is open). Every option opens an export modal with file size, a copy-to-clipboard button, and a download button. On a phone the topbar has no room for that button — take ⋯ More → Export… instead, which opens the same menu (the whole toolbar moves there).

What data travels with an export. A source with no engine behind it — sample-pack content, authored datasets, View Builder results — can't be re-queried from a standalone file, so the export always bakes in a data snapshot taken at export time: the file shows real numbers anywhere you host it, and simply doesn't update until you export again. (View Builder Views snapshot their actual computed rows.)

Live data sources pick a data mode. When the dashboard queries live remote sources (a connected database, a Google Sheet, a warehouse…), the .html export first asks what should travel inside the file:

Dashboards with no live remote source skip the dialog — everything in them is already a snapshot. (A dropped local file's data always travels inside the export; it needs no mode.)

FormatWhat you getUse when
Dashboard (.html) A fully self-contained .html file with all toolkit JS/CSS inlined. No server required — open in any browser. (Internally this is the Dashboard Framework export — the name you'll see in a text View's inspector note — but the button says Dashboard (.html).) Sharing demos, embedding in portals, or hosting as a standalone dashboard on any static web host.
Excel workbook (.xlsx) A genuine multi-sheet Excel workbook (opens in Excel, Google Sheets, or LibreOffice — no warnings, built entirely in your browser with no upload). Tab 1 is a Dashboard summary: the title, every KPI with its value, the list of Views (title, chart type, data source), and any filters. Each following tab holds the backend data behind one data source the dashboard uses — its columns and rows — with two Views on the same source sharing one tab. Downloads straight to your machine. Handing the numbers behind a dashboard to someone who wants to pivot, chart, or re-cut them in Excel — the visual on tab 1, the raw data right after.
Word document (.docx) A genuine Word report (opens in Word, Google Docs, or LibreOffice — built in your browser, no upload). The dashboard title and description, a KPIs table (name + value) and a Views table (title, chart type, data source), then a table of the backend data behind each data source the dashboard uses. Downloads straight to your machine. Dropping the dashboard's numbers into a written report, memo, or brief — headings and tables you can edit, not a picture.
PowerPoint (.pptx) A slide deck (opens in PowerPoint, Google Slides, or LibreOffice Impress — built in your browser, no upload). A title slide, a KPI slide (each KPI with its value), then one slide per View carrying that View's chart as a full image (rasterized from the live preview); a table/text View that has no chart falls back to a text slide naming its data source. Turning a dashboard into a walkthrough deck for a meeting — one chart per slide, ready to present or annotate.
PDF (print) Asks for page size (Letter/A4/Legal), orientation, and scale, then opens the same self-contained dashboard export in a new tab and starts your browser's print dialog there — choose "Save as PDF" (or a real printer). A print stylesheet keeps Views/KPI rows from splitting across a page break and sets sane page margins; "Fit to page width" (the default) scales a wide dashboard down uniformly so nothing gets cropped at the page edge. A one-off PDF or hard copy of the current dashboard, sized for the paper you're printing to — no separate export step to manage.
Editable spec (.studio.json) The dashboard's own source of truth — the JSON spec the builder reads and writes. It carries the layout, every View and KPI, the filters and the dataset references, and nothing else: no toolkit, no baked rows, so it stays small. Open it again with Open… → Open file…, or publish it anywhere public and hand out the link (Import from URL…). Version-controlling a dashboard, handing it to someone who will keep editing it, or moving one between workspaces.
All artifacts (bundle) Both artifacts together — the .html and the editable .studio.json spec. Full delivery: the rendered dashboard plus its editable source of truth.

Saving and loading your work

Embedding a single View

Select any View and click Export this View… in its inspector to download a tiny, self-contained .html View with just that one chart — the same toolkit, minus the rest of the dashboard's KPIs, filters, and other Views. Drop it anywhere you'd embed a standalone chart.

Saving a chart as an image

Select any View and click Save chart as PNG in its inspector to download the chart itself as a PNG image — handy for dropping into a slide deck or a doc. This covers chart types that render as SVG (the vast majority) plus the Map (US choropleth) chart's Interactive GL renderer (captured straight off its canvas); Table and Richtext Views don't support it yet. The image is the chart only — for donut/gauge-style charts whose legend is drawn inside the chart it's included, but a legend rendered as a separate element next to the chart is not.

Downloading a View's image or data, right on the canvas

Hover any View — in the builder or a published/embedded dashboard — and a small Export button appears in its top-right corner, offering:

Each is on by default and can be turned off independently per View under the inspector's Downloads section — useful for a View you don't want viewers exporting from a published dashboard.

Saving a View to the View library

Select any View with a bound query and click Save to View library in its inspector to snapshot it as a reusable View — the same View library Quick Views saves into. Give it a name and it shows up in the builder's Data panel under Views (drag it onto the canvas, or use its "+ Add to dashboard" chip) and in Quick Views' own saved list, exactly like a View built there. It's a self-contained copy — editing or deleting the original View's dashboard afterward doesn't affect it. Not available for Richtext/annotation Views, which have no query to snapshot.

Keyboard shortcuts

These listen on the page, not on one pane, so they work anywhere in the app — with one exception that covers all of them: nothing fires while you are typing in a text field, a text area or a dropdown. The rows marked View selected act on whichever View is selected on the builder canvas, so select one first. Open the same reference in the app with ?.

KeysAction
Ctrl K / ⌘ KOpen the command palette (works from anywhere, any section)
Ctrl Z / ⌘ ZUndo the last structural edit
Ctrl Shift Z / ⌘ Shift ZRedo
Ctrl Y / ⌘ YRedo — the Windows alias, same action
Ctrl S / ⌘ SSave to your Dashboards catalog
Ctrl D / ⌘ DDuplicate the selected View or KPI
Ctrl F / ⌘ FFocus the builder's Data panel search — on a phone this opens that pane's drawer first
/Focus the chart-type gallery's search box (View selected, gallery on screen)
↑ / ↓Reorder the selected View up / down
Shift ← / Shift →Resize selected View span narrower / wider
Delete / BackspaceDelete the selected View or KPI
EscapeLeave Focus mode; deselect the View; close any open modal or menu
TabMove through the interactive controls of whatever is on screen
?Open / close the keyboard shortcuts reference modal

The in-app shortcuts overlay closes with two things that aren't keys, so they have no row above: double-click a View's title on the canvas to rename it inline, and the ↗ button on a View zooms it to full screen (Escape closes it again).

Reading a dashboard without a mouse

In the Viewer and in any dashboard you've exported as a self-contained file, KPI tiles are buttons: Tab moves through them, a focus ring shows which one you're on, and ↵ or Space opens that tile's detail — the same drawer of underlying records a click gives you. Inside the drawer, Escape closes it.

The same is true of the chart marks that do something when clicked — the bars of a bar chart, the slices of a donut, the tiles of a treemap, wherever that View has a detail drawer or a click-through set up. Tab stops on each one and ↵ or Space activates it. Because a bar or a slice has no text of its own, each one announces itself as its label and value — "Snowflake: $84.2K" — so a screen reader reads the same fact the hover tooltip shows. Marks that aren't clickable stay out of the way entirely. On the Studio canvas, clicking a mark still selects the View for editing, so the builder's keyboard behaviour is unchanged.

The tooltip opens on focus, too. Tabbing onto a mark pops the same tooltip card hovering it with a mouse would — the exact figure, the percentage, the share of the total — anchored to the mark itself rather than to a cursor that isn't there. It disappears when you tab away, and Escape dismisses it on the spot without losing your place, so a card sitting over the next bar is never in your way. Reaching a mark with the mouse is unchanged: the tooltip keeps following the pointer.

Table rows that open a detail drawer work the same way from the keyboard — Tab stops on each clickable row, ↵ or Space opens the drawer — with one deliberate difference: a row is not turned into a button. Doing that would stop it being a row, and a screen reader would lose the table itself (which column you're in, which header a cell belongs to). So the row keeps its table semantics, announces that it opens a dialog, and reads out its own cells rather than a summary. Sorting, filtering and paging redraw the table, and every new page behaves the same; a table with no detail drawer bound keeps its rows out of the tab order.

Command palette

Press Ctrl K / ⌘ K anywhere in the app — or click the Search… pill in the top bar — to open a fuzzy-searchable list of commands, then jump straight to any of them by typing part of its name. Use ↑/↓ to move, ↵ to run, Escape to close.

Every row carries a small family tag on the right, and the palette prints fourteen of them. Section and Reference are the left rail's own places to go — that list is built from the rail itself, so a section your role can't reach (or one an admin has turned off for viewers) is missing from the palette too, rather than being offered and then refused. Create, File and Export are the dashboard lifecycle: a new or a sample dashboard, opening and saving one, and the three export formats. Edit is undo, redo, adding a text View and editing the JSON spec; Data is a new dataset or connection. View and Present are the modes — light/dark, Focus mode, Simple mode, Slideshow, Demo mode. Learn is the welcome tour, the interactive tutorial and this keyboard reference (it is the family every tour means when it says "⌘K → Interactive tutorial"), and Manage is clear local data and sign out. Sample and Recent are every curated example and every dashboard you've opened, and Add View is one command per chart type in the gallery.

Five of those families are labelled from whatever the workspace currently holds, so each one reads as a fixed prefix plus the thing's own name — and the prefix is what you type to reach the family: "Go to <section>" (with "Open Help & docs" as the one section that reads as a reference to open rather than a place to go), "Open sample: <name>", "Open dashboard: <name>", and "Add View: <chart type>", which creates a View bound to a catalog query and switches it straight to that type. These are the words the palette matches on, so they are the ones worth typing: search covers a command's visible label, its family tag and its hidden synonyms, and — like every other search box in the app — every term you type has to match, in any order. Those hidden synonyms are why an older word still works: a View on a dashboard used to be called a panel, and typing that still finds both commands that add one.

Open the palette with an empty box and the commands you have run before come first, most recently run first — that ordering is recency alone, not a popularity chart. How often you have run something counts only once you start typing, and only as a tie-breaker: how well a command matches what you typed decides the order, and usage separates commands that match equally well.

Voice command mode: on a browser with the built-in Speech Recognition API (Chrome, Edge, Safari — no API key, no backend, no sign-up), the palette shows a small mic button beside the search field. Click it, say a command out loud ("add a bar chart", "go to settings", "toggle light dark theme"), and it runs the same way pressing ↵ on that text would — fully hands-free. The mic pulses red while listening and stops on its own once you finish speaking. Not shown at all in browsers without the API (e.g. Firefox) — typing still works everywhere.

Glossary — every term, one line each

These are the app's own words, not ours: every kind of thing you can make (the five the Repository indexes), every place you make it (the three builders on the rail's Build group), and the two ways they are filed. One line each, spelled the way the screen spells it.

Simple mode vs Advanced mode

There are four ways in, and they are the same switch — flip it anywhere and every other one follows. The ⋯ More menu; the ⌘K command palette (type “simple”); the two quick switches at the foot of the left rail, where Simple mode sits beside Dark mode; and the Settings page, where it is one of the switches in the Mode group. The setting persists across sessions, and while it is on the top bar carries a Simple mode badge, so you always know which mode you are in.

Simple mode

What it takes away:

Nothing outside the builder changes. The workspace catalog pages keep every authoring control in both modes — the Repository page still offers Quick edit on a row, + New folder, and the Select bulk bar, and Datasets, Connections, Jobs and Views are untouched. Simple mode is a quieter builder, not a read-only app.

And what it adds, all of it in the builder:

Advanced mode (default)

The Settings page — every card on it

Settings is pinned at the foot of the left rail, and it is one scrolling page of cards. In the order they appear:

  1. Account — who you are signed in as, with your role beside the name (and a demo account note when it is one), and the Sign out button. This card is why Settings stays in the rail for a viewer even when an admin has switched every other section off.
  2. Workspace backend — which workspace this browser is working in and whether it is syncing, with Connect / Switch backend, the Recent sync activity log and the access-file export. It has a chapter of its own: Admin & backend setup.
  3. Appearance — Dark mode, plus the Color theme picker's palette cards.
  4. Mode — three switches: Simple mode, the subject of this chapter; Restore unsaved work, off by default, which offers on your next visit to bring back a dashboard you were editing but never saved; and Open the builder with side panes, also off by default, which decides whether the Dashboard Builder opens with its Data and Inspector panes already out.
  5. Presentation — Demo mode, which simulates a live-refreshing feed for a stakeholder demo, and Welcome tour, whose Take the tour button re-runs the guided walkthrough. This card is where the tour lives; it is not on the top bar, and ⌘K → Take the tour reaches the same thing.
  6. Dashboard defaults — the house style every brand-new blank dashboard starts from, plus Style presets. Detailed immediately below.
  7. Sample packs — install or remove each sample pack, one pack at a time, with each card naming where its data came from. This is the only sample-content switch there is.
  8. Data — Export settings / Import settings, described under Backing up your settings below.
  9. App — Hard reset, which throws away this browser's offline copy of Analytics (its service worker and cached files) and reloads so every file is fetched fresh. It is the remedy for an update banner that keeps coming back however often you reload. It removes nothing you have made — your workspace, dashboards, datasets, connections and settings are all untouched — which is what makes it different from ⋯ More → Clear local data, and the one to try first.

Three more cards look like Settings cards but live on the Admin page instead, because they are app-wide rather than yours: Section access, Workspaces and Branding & app identity.

Dashboard defaults

The Settings page's Dashboard defaults card sets the house style every brand-new Blank dashboard starts from — handy for teams with a house tagline, brand color, logo, or whole-look theme. Seven fields, each matching its per-dashboard counterpart:

Existing dashboards, examples, and imports are never touched. Carried along by Export/Import settings and included in Clear local data.

Below that, Style presets lets you save the current set of defaults above as a named preset — type a name and click "+ Save as preset". Save more than one (e.g. one per client) and click Apply on any saved preset to switch which one is the active default; the trash button removes a preset. The preset whose saved fields match your current defaults is marked Active (a highlighted row + pill), so you can tell at a glance which house style is live — change any default and the marker clears until a preset matches again. A preset with a saved logo shows a small thumbnail instead of a plain color swatch. Presets travel with Export/Import settings and are included in Clear local data too.

Backing up your settings

The Settings page has a Data card with Export settings / Import settings. This saves/restores your theme, mode, workspace connections, and pane-layout preferences as a .json file — handy before clearing local data, or to carry your setup to another browser or device. It only covers app preferences, not dashboard content (use Save / Open for a .studio.json).

Branding & app identity

The Admin section has a Branding & app identity card — it's app-wide (what everyone who opens the workspace sees), so only admins can change it. It controls three things:

Branding is saved with the workspace — on a connected workspace it syncs to the backend and applies for everyone who signs in, on every device (a custom logo shows on the sign-in screen too). Export settings also carries a copy along. This only affects the app's own chrome — it's independent of any exported dashboard's branding.

Sending feedback (and what gets recorded)

The speech-bubble button in the top bar (next to What's-next) opens a tiny dialog — on a phone the top bar keeps only its essentials, so you'll find Send feedback in the ⋯ menu instead, right below What's new. Either way: pick a kind — Bug, Feature, Comment or Question — optionally say more, and hit Send.

Alongside what you typed, the report carries a small block of context, captured automatically so that a one-word report still tells the team exactly where you were. This is the whole of it: your account name and your sign-in id (both empty if you aren't signed in), the section you were on, the open dashboard's id plus its title (only when one is open), the route in your address bar, the app version, your window size, and your browser's user-agent string. Nothing else travels with it — not the contents of the page you were on, and none of your workspace data.

Reports go to an admin-only log in the workspace backend; on a local-only workspace they wait on your device and send once a backend is connected. Separately, the backend keeps a concise activity trail — sign-ins/outs, dashboard opens, exports, and one time-on-page event per visit — also admin-only, with nothing visible to anonymous readers.

On the deployed site the trail covers anonymous and local visits too: a visitor who never signs in (or signs in to a local-only account) still records a sign-in-screen view and a time-on-page event, delivered through the packaged Polecat workspace. Those rows carry the route, referrer, and viewport from the browser, and the server stamps the requester's IP address and user agent on arrival (a browser can't see — or spoof — its own public IP). Writing is all anonymous visitors can do: the log stays admin-only to read, and an anonymous row can never claim a signed-in identity. Local development pages never send anything.

Color theme

The Settings Color theme picker — seven palette cards, each previewing its real colors
The Color theme picker

The Appearance card on the Settings page has a Color theme picker (separate from the Dark mode switch) — clickable palette cards, each previewing its own actual chrome colors so you pick by looking. It offers the same seven looks as the Dashboard theme picker, so app chrome and dashboards read as one system:

Good to know: