Skip to content

Dashboard folder layout

A dashboard in PlotPress is a folder, and a self-contained workspace. The folder name is the dashboard’s URL slug. Connections, users, and pages all live inside it.

plotpress/
├── plotpress.yaml # server config (listen, auth, storage)
└── dashboards/
├── sales/ # → /dashboards/sales/
│ └── ...
└── ops/ # → /dashboards/ops/
└── ...

One server-level file. Everything else is a dashboard folder.

dashboards/sales/
├── dashboard.yaml # required, but tiny
├── connections.yaml # data sources this dashboard reads
├── users.yaml # roles + membership rules
├── index.md # the landing page
├── revenue.md # → /dashboards/sales/revenue
├── customers.md # → /dashboards/sales/customers
└── queries/ # OPTIONAL — only for the SQL fallback
└── _shared.sql

Four conventions:

  1. dashboard.yaml is required, but most dashboards only need title and connection.
  2. connections.yaml declares the data sources this dashboard can read. No inheritance from outside.
  3. users.yaml declares the roles allowed on this dashboard.
  4. Every .md file is a page, named by its filename (index.md is the folder root).

queries/ is optional. Plot blocks reference database views by default; queries/*.sql only exists when the database doesn’t expose a view that fits — see Connections for that fallback.

title: Sales
connection: warehouse # default for views in this dashboard

Two fields. That’s the floor.

---
title: Revenue
---
Revenue is recognised on invoice date. The warehouse refresh runs hourly;
this page reflects the last completed refresh.
## Monthly revenue
```plot view=monthly_revenue
Plot.barY(data, { x: "month", y: "revenue", fill: "currency" })
```
## Top customers
```plot view=top_customers params.limit=20
Plot.dot(data, { x: "deals", y: "revenue", r: "lifetime", tip: true })
```

monthly_revenue and top_customers are views in the warehouse. The dashboard’s connections.yaml decides which database those views live in; nothing else needs to be wired up.

PropertyWhat you get
Diff-friendlyA PR that touches “sales” only touches dashboards/sales/. Reviewers see the unit.
Move-friendlygit mv dashboards/sales dashboards/finance/sales is the rename. The URL follows.
Self-containedConnections and users are in the folder. Auditing “what can sales read?” is one cat.
Template-friendlyA new dashboard is cp -r dashboards/_template dashboards/new.
No hidden stateDelete the folder, the dashboard is gone — including its query surface area, which matters for security review.