Help
Everything Prism does, on one page. Press Ctrl+F.
Pages
A page holds questions, text and filters. There's no separate dashboard: readers see the page, and anyone who can edit clicks a block to open it in the side panel. Changes save themselves.
- Width: each block can be full, half, a third or a quarter of the page.
- Moving: drag a block by its handle, which appears when you hover.
- Hiding: a block that only feeds other blocks can be hidden from readers, and readers of a shared link can't fetch it. It still runs when something needs it. The one exception is a hidden block that fills a filter's choices or feeds a Python block, since their browser needs that.
- History: the page menu keeps earlier versions. Restoring is undoable too.
- Comments: from a block's menu. They reach whoever made and last changed the page, and anyone already in that conversation, by email when this server has email set up.
- Working together: you'll see who else is on a page, and their changes arrive within seconds. Two people editing different blocks never conflict.
- Search: Ctrl+K (⌘K on a Mac) finds any page, table or metric. Type a whole question there and it asks it.
- Freshness: the page menu sets how old its numbers can get. Left open, a page keeps itself current, so it works on a wall screen. On a warehouse, longer means fewer queries to pay for.
- Views: the Pages screen shows how many times each page was opened in the last 30 days, by anyone but whoever last edited it, so you can tell what people read and clear out what they don't. It's a count, and it doesn't record who.
- Stars: star a page and it stays at the top of your sidebar. Stars are yours alone.
Asking
Type what you want to know: on the home screen, in Explore, at the foot of a page, or on a block.
Prism reads your own table names, column names, values and metrics, so this works with no setup:
revenue by monthtop 10 products by revenuerefund rate by category in the west last 90 dayshow many orders by channel this yearaverage shipping days by region excluding refundedshare of revenue by channelwhat's our best selling productrevenue growth by month
You always see how it was understood, as the same sentence you could have clicked together, so fixing a misreading is one click. Words it couldn't place are listed.
When a server has Claude set up, it takes over for questions those rules can't place. Claude sees table names, column names and metric definitions. It never sees your rows.
Building
Every question reads as a sentence: From a table, Show what to measure, By how to split it, Where what to keep. Results update as you click.
A join can't inflate a total. Each row only ever matches one row in the table it points at. If that table has the same id twice, Prism won't join to it, and says so, until it's fixed.
Joins are automatic. A column called customer_id reaches a table called customers, and its columns appear in the lists. Joins only go from a row to the one thing it points at, so a total can never be counted twice.
When names don't say: foreign keys declared in Postgres and MySQL are read automatically. For anything else, like buyer_id pointing at users, choose Link to another table in Explore or on the table's page. Prism checks the column you point at has one row per value, so that promise still holds.
Time grains come from the data: click a date column and pick day, week, month, quarter or year.
As a share, running total or growth: when a question splits a number, As shows it as a share of the total, a running total, or growth on the one before. Split over time as well, a share is of that period. It's worked out on the whole answer, so a top 5 still shows each one's share of everything.
Against the previous period: when a question is one number, Against shows how it moved. The last 30 days are compared with the 30 before. A page's date filter works too: a whole month against the month before, a month or year so far against the same days of the last one, anything else against the same number of days just before. With no period chosen, it's just the number. Asking works as well: “revenue last 30 days vs the previous 30”.
Running totals and snapshots: a balance or a cumulative count can't be added up across days. In a date filter, is the latest keeps only the most recent date, within whatever else is filtered. Prism notices columns that only ever go up, and asking about one, or making a page from its table, uses the latest figure and says so.
Switching to SQL carries the question over, with its filters and metrics intact.
SQL
Ctrl+Enter runs. Tables, columns, blocks, @metrics and {{inputs}} all autocomplete.
On tables in Prism, the dialect is close to Postgres. Worth knowing:
- Dates:
date_trunc('month', d),CURRENT_DATE,d - INTERVAL '30 days',extract(year FROM d),to_char(d, '%Y-%m').CURRENT_DATEis in UTC here; date filters and questions follow your own day. - Conditional totals:
sum(x) FILTER (WHERE y = 'a'), orsum(CASE WHEN … END). - Windows:
lag(x) OVER (ORDER BY d),row_number(),rank(), running totals. - Text:
lower,upper,concat,split_part,regexp_replace,ILIKE. - Everything else:
median,approx_distinct,nullif,coalesce,WITH,QUALIFY.
Prism only reads, so CREATE, INSERT, UPDATE, DELETE and SET aren't available. Functions whose output size is set by an argument (repeat, lpad, rpad, generate_series) are turned off.
On a connected database, you write that database's own SQL.
Filters
Add filters from the row above the page. They scope every block on it, readers can change them, and the current values live in the link, so what you send is what they see.
In SQL that's the whole template language:
SELECT *
FROM orders
WHERE order_date >= {{period.start}}
AND order_date < {{period.end}} + INTERVAL '1 day'
[[ AND channel = {{channel}} ]]
{{name}}is the input's value, always escaped, so a reader can't change the query's shape.{{period.start}}and{{period.end}}are a date range's two ends.{{period.prev_start}}and{{period.prev_end}}are the period to compare it with: the months just before whole months, the same days of last month or last year for a month or year so far, otherwise the same number of days just before.[[ … ]]drops out when an input inside it is empty or set to All.
In a built question, click a filter and choose Link to page filter. If a chart splits by something a page filter controls, clicking a bar offers to filter the page.
Blocks reading blocks
Every question has a name (it's at the bottom of the panel), and any other block can read it like a table:
SELECT month, revenue FROM monthly
There's no run order and no hidden state: Prism works out what depends on what, and runs what's needed. Rename a block and the queries reading it follow.
This is also how to join across sources. Write a block against your database, then read it from a block that joins it to an uploaded file.
Save as a table (in a block's menu) keeps a block's answer as a real table, refreshed hourly or daily if you like. Use it to make slow queries fast.
Python
Add a Python block at the foot of a page. It runs in your own browser, with pandas, numpy, matplotlib, scipy and scikit-learn to hand. Nothing is installed and there's no kernel to restart.
top = paid_orders.groupby("channel").amount.sum()
top.sort_values(ascending=False)
- Other blocks: name one, like
paid_ordershere, and it's there as a DataFrame, with all its rows, up to half a million. If it has to stop short, the block says so. - Filters: they're in
inputs, likeinputs["channel"]. - Output: the last line becomes the chart or table. Whatever you print or plot shows below it.
- Safety: code runs in a sandbox with no network and no access to your account, so a shared page's Python can't do anything as you. It stops after two minutes.
- The catch: SQL blocks can't read a Python block's result, because SQL runs on the server. Readers of a shared page can see that page's Python, though never its SQL.
Metrics
A metric is a name, a definition and an owner, so everyone means the same thing by a number:
sum(amount) FILTER (WHERE status = 'paid')
It appears first in Explore and in every builder, and @revenue works in any query. Change the definition and every page follows. A definition is checked against the table when you save it, so a broken one can't reach anyone.
Renaming one updates every page and metric that uses it. The metric's window lists what uses it, and deleting one tells you what will stop working first.
Why did this change? On any metric, this compares two whole periods across every split Prism can reach, and ranks what moved the number.
Data
Files: drop a CSV, TSV, Excel (.xlsx), JSON or Parquet file anywhere in Prism. Types are read from every row, so a stray value can't surprise you later, and a zip code keeps its leading zero. Rows that don't fit are counted and reported, and the rest still load.
Links: add a table from a Google Sheet or a link to a CSV, Excel, JSON or Parquet file, and Prism reads it again every day or every hour. A Google Sheet needs its sharing set to “Anyone with the link can view”. If a read fails, or the file has lost a column something uses, the table stays as it was and its page says why.
Databases: Postgres and MySQL on a public address, Snowflake and BigQuery. Use a read-only user, and for Postgres and MySQL allow connections from 46.4.105.186. Prism only ever runs one read-only statement at a time, with a time limit and a row cap. Credentials are stored encrypted.
On Snowflake, use a programmatic access token for a read-only role. Snowflake needs a network policy on that user allowing 46.4.105.186, and tokens last 15 days unless you choose longer, up to a year. A new one goes in the connection's settings, and every page carries on.
On BigQuery, you set the most one query can bill. BigQuery itself refuses anything over that, so one careless query can't run up a bill.
Click a table for a summary of every column and its first rows, and what uses it. Make a page from this builds a first page from what's in it. Click a connection to browse its tables and explore them the same way.
Changing data safely: rename a table and every page and metric follows, including saved SQL. Replace it with a file that's lost a column something uses, and Prism names the column and what uses it before anything changes. Deleting a table or connection says what will stop working first.
Team
In Settings, invite people with a link. Owners manage the workspace and its connections. Editors change pages, data and metrics. Viewers read pages and tables, change filters, comment and ask their own questions, and can't change anything.
Anyone trying Prism without an account keeps their work for 14 days. Creating an account keeps everything where it is.
Coming from elsewhere
- Looker: on the Metrics screen, paste a LookML view, and its measures become metrics, each checked against your table. Paste a model file too, and its explores' joins become links, each checked so a total can't double. Anything that can't come across is listed with the reason.
- Looker dashboards: in Looker, choose Get LookML on a dashboard and save it as a
.dashboard.lookmlfile. On the Pages screen, choose Import. Its tiles, filters and layout become a page of built questions. Bring the view's measures across first, so they're metrics. Anything that can't come across is listed with the reason, above all a filter that would change a number. - dbt: on the same screen, paste a file with
semantic_modelsormetrics, in either of dbt's formats. Simple metrics and ratios come across, filters included. Choose the connection first if the tables are in your warehouse. Cumulative and conversion metrics don't have an equivalent, and are listed. - Deepnote and Jupyter: on the Pages screen, import a
.deepnoteor.ipynbfile. SQL, text and Python all come across as blocks. - Mode and anything else: paste the SQL into a block.
{{ name }}works the same way. - Leaving: download any page as a plain file from its menu, and any result as CSV.
Limits
Limits keep one query from slowing down everyone else. When you hit one, Prism says which.
| A query can run for | 30 seconds |
|---|---|
| A query can use | 512 MB of memory, and 2 GB of disk while sorting |
| A result can hold | 1,000,000 rows on Prism's tables, 200,000 from a connected database. The first 5,000 show on screen; downloads get them all, and Python up to half a million. |
| A file can be | 250 MB with an account, 25 MB when trying it out |
| A workspace can hold | 5 GB with an account, 50 MB when trying it out |
| A page can hold | 200 blocks |