Combine Reports into Decks and Dashboards
Overview
A deck is a list of reports that produce one document instead of several. uc-bq deck run builds
a PDF with a branded cover page, a clickable table of contents, and each report on its own page.
uc-bq deck dashboard takes the same definition and produces an interactive HTML page instead.
Both read from the reports you already have, so nothing about the individual reports changes.
Deck definitions are YAML files in reports/{merchant_id}/decks/ and belong in Git; the
generated PDF and HTML do not.
reports/DEMO/decks/
├── weekly-executive.yaml # Definition, committed
├── weekly-executive.pdf # Generated by deck run
└── weekly-executive-dashboard.html # Generated by deck dashboard
Create a deck
Pass a title and the reports to include:
uc-bq deck create weekly-executive \
--title="Weekly Executive Briefing" \
--reports=revenue-by-payment-method,ltv-by-monthly-cohort,top-products-by-revenue \
--company="DEMO Commerce Inc." \
--logo-url="https://example.com/logo.png" \
--landscape
deck create is not interactive. Running it with only a deck name prints the reports available
to you and exits without writing anything. Both --title and --reports are required.
The name recorded inside the file comes from --title, while the file name comes from the
deck name argument, so the two are not the same thing.
Writing the file by hand works equally well:
# reports/DEMO/decks/weekly-executive.yaml
name: "Weekly Executive Briefing"
title: "DEMO Weekly Report Deck"
cover:
company: "DEMO Commerce Inc."
logo_url: "https://example.com/logo.png"
parameters:
start_date: "start_of_year"
end_date: "today"
reports:
- revenue-by-payment-method
- ltv-by-monthly-cohort
- top-products-by-revenue
landscape: true
delivery:
slack:
channels: ["C0123456789"]
email:
to: ["ceo@example.com", "cfo@example.com"]
subject: "Weekly Executive Briefing"
provider: "sendgrid"
name, title, and reports are required; everything else is optional. Reports are rendered in
the order listed, and each name has to match a report directory under reports/{merchant_id}/.
Omitting cover leaves a cover page showing only the title and the resolved date range.
Build and deliver the PDF
uc-bq deck run weekly-executive
uc-bq deck run weekly-executive --deliver
uc-bq deck run weekly-executive --no-analysis
uc-bq deck run weekly-executive -m DEMO2
Each report in the deck runs in turn, so a deck run refreshes the underlying data as well as
building the document. Add --no-analysis when you want the charts refreshed without paying for
written commentary.
With --deliver, the deck PDF goes out as a single file to the channels configured in the deck's
own delivery section. The individual reports are not delivered separately: the deck replaces
them. Slack and email setup is identical to a single report, covered in
Report delivery.
A deck can also be set to stay quiet unless something is wrong:
uc-bq config set-deck-delivery-mode weekly-executive alarm_only
Alarms raised by the individual reports are collected into one deck-level notification. See Report alarms.
Control the date range across every report
A deck's parameters section pushes shared values down to its reports, which is usually how you
get five reports onto the same date range:
parameters:
start_date: "start_of_year"
end_date: "today"
The values accept the same relative date expressions as report defaults and resolve each time the deck runs.
How hard those values push depends on parameter_mode:
smart, the default, only replaces static dates such as2025-06-15. A report whose default is already a relative expression like-90dorstart_of_yearkeeps its own behaviour, so a rolling report stays rolling.overridemakes the deck's values win over every report default.
Per-report overrides sit above both, and are written by using an object instead of a plain name
in the reports list:
parameter_mode: smart
parameters:
start_date: start_of_year
end_date: today
reports:
- revenue-by-payment-method
- name: ltv-by-monthly-cohort
parameters:
start_date: start_of_last_year
The full precedence order, highest first, is: flags on the command line, per-report overrides in
the deck, the deck's parameters section, then each report's own defaults.
Override everything for one run:
uc-bq deck run weekly-executive --start_date=2026-01-01 --end_date=2026-03-31
Or change the stored values without editing YAML:
uc-bq config set-deck-param weekly-executive start_date start_of_year
uc-bq config show-deck-params weekly-executive
uc-bq config remove-deck-param weekly-executive start_date
Generate an interactive dashboard
The same deck definition produces a single HTML file with live charts:
uc-bq deck dashboard weekly-executive
uc-bq deck dashboard weekly-executive --open
The result is written to reports/{merchant_id}/decks/{deck-name}-dashboard.html. Charts respond
to hover, show tooltips, and support zoom, and the grid drops from two columns to one on narrow
screens.
The dashboard is built from the data.json files already sitting in each report directory, so it
does not run any queries and costs nothing. If a report has never run, run the deck or
uc-bq run-all first.
Choose between the two outputs based on how it will be read:
deck run | deck dashboard | |
|---|---|---|
| Output | Static PDF | Single HTML file |
| Charts | Rendered images | Live charts with tooltips and zoom |
| Distribution | Slack and email via --deliver | Deploy or share the file yourself |
| Read in | A PDF reader | Any browser |
The HTML is self-contained apart from loading ECharts from a CDN, which means the reader needs
network access when they open it. Put it on S3 with Content-Type: text/html, drop it into any
static web server, or just open it from disk. The CLI does not deploy it for you.
List what you have
uc-bq deck list
Related Documentation
- CLI reference - every
decksubcommand and flag - Report delivery - Slack and email setup shared with decks
- Report alarms - alarm rollup across the reports in a deck
- Configuration reference - the date expressions deck parameters accept