Prism

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.

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:

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:

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}} ]]

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)

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.

Sharing and sending

A link: anyone with it can read the page, use its filters and download what they see. They can't see your queries or change anything. Turning it off kills the link at once.

A link locked to a filter: for sending someone only their part, like one client's numbers. Set the filter on the page, then create a locked link in the Share dialog. The value is fixed on the server, and the control is gone, so nothing they do can change it. Their other filters still work. The dialog lists any block that doesn't use the locked filter, because they'd see all of that one. If the filter is later removed from the page, the link stops working rather than showing everything.

On your own site: the Share dialog gives you an embed code, and a locked link embeds the same way.

Inside your own product: Settings gives you a signing secret. Your server signs a short-lived token for each visit, naming a page and the filters to fix, so one page can serve every customer you have, with nothing to set up per customer. It's a standard HS256 JWT:

header:  { "alg": "HS256", "typ": "JWT", "kid": your workspace ID }
payload: { "page": page ID, "locked": { "customer": "Acme" }, "exp": seconds since 1970 }
then:    /prism/s/<token>?embed=1 in an iframe

An expiry is required. Replacing the secret stops every token signed with the old one.

On a schedule: from the page menu, send its headline numbers to Slack, a webhook or email, hourly, daily or weekly, with a link back.

Alerts: from a number's menu. It's checked every hour, and you hear once when it crosses your line, not every hour after.

On paper: the page menu prints every block, or saves it as a PDF.

Carrying on: anyone in the workspace can choose Explore from here on a built chart. It opens the same question, with the page's filters written in, ready to change.

Trust: click a bar in a built question to see the rows behind it. A period that hasn't finished is drawn dashed, so a half-finished month doesn't look like a collapse.

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

Limits

Limits keep one query from slowing down everyone else. When you hit one, Prism says which.

A query can run for30 seconds
A query can use512 MB of memory, and 2 GB of disk while sorting
A result can hold1,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 be250 MB with an account, 25 MB when trying it out
A workspace can hold5 GB with an account, 50 MB when trying it out
A page can hold200 blocks