No saved queries yet. Run a query and click ⊕ Save to save it.
R Script library
No saved R scripts yet.
Admin
Users
Username
Email
Role
Board
Last login
Boards
Board
Members
Widgets
Min recompute
API key (global)
Notification channels
— where alerts get delivered (Slack webhook or email)
Name
Type
Target
Enabled
Threshold rules
— per-widget conditions that fire a channel on each ok→firing transition
Widget
Condition
Channel
State
Last fired
Recent firings
— last 100 alert evaluations that crossed into firing
Time
Widget
Value
Threshold
Channel
Delivered
Query timeout
— how long a MySQL query is allowed to run before being killed
The server kills any single SELECT that exceeds this many seconds. The default is set by the MYSQL_QUERY_TIMEOUT env var (currently —s). Raise it here if widgets are consistently timing out. Per-widget overrides can be set in the widget editor (global admins only).
Server caches
— flush after editing a filter template, CPM rules, or any widget SQL referenced by these caches
The server caches two heavy reads. Filtered-snap caches widget results per filter-value combination so repeated filter clicks are instant. CPM eligible stores caches the latest-row-per-store scan of fraznetapp_cpm for the {{cpm_eligible_stores}}/{{cpm_latest}} tokens. Both refill on the next request after a flush.
HubSpot API connection
— Private App token used by Python widgets
Paste a HubSpot Service Key token (or legacy Private App token). Widgets running Python get it as the HUBSPOT_TOKEN environment variable.
Step-by-step setup ↗
HubSpot query library
— reusable Python snippets users can drop into widgets
Name
Description
Updated
HubSpot dashboards (PNG snapshots)
— snapshot URLs you can drop into Presenter mode
Label
Dashboard ID
Last snapshot
Pages
Dark mode
Kiosk URL
Other external dashboards (Genesys, Salesforce, generic)
— snapshot URLs you can drop into Presenter mode
Label
Kind
Last snapshot
Pages
Dark mode
Kiosk URL
After adding a source you need to seed its login session once: python bootstrap_session.py --source <source_id> on your local machine, then scp the resulting JSON to the server path shown.
Add widget
Stat
Gauge
Line chart
Bar (time)
Progress
Badges
Cache table
R Script
Status light
Funnel
Histogram
Calendar heatmap
Category bars
Grouped chart
Result table
Pie / Donut
Map
API
Note
⅛
¼
⅓
½
¾
Full
½ row
1 row
2 rows
3 rows
4 rows
Left
Center
HubSpot library:
Chart history builds up over each poll cycle.
Optional format per row: Label | SQL | format — e.g. integer, currency, currency_gbp, percent_raw.
Lines starting with --- become full-width section headers (e.g. --- This Week).
Vertical ▐
Horizontal ▬
Useful in kiosk mode where hovering for tooltips isn't possible.
Toggle the inline labels (region names on the map, slice values on charts, etc.). Tooltips and the colour fill stay regardless.
Path should resolve to a single value
Pie
Donut
Show
Hide
A fixed number or a single-value SQL query. The gauge fills proportionally from 0 to this target. The "Query / Script" above is the current value.
Two-column result: label, value. Order rows in the query — the first row is the top of the funnel.
One-column result: a numeric observation per row. The first column is used if more than one is returned.
How many equal-width buckets to split [min, max] into. 2–100.
For "Higher is better": value ≥ Good → green, ≥ Warn → amber, else → red. For "Lower is better": ≤ Good → green, ≤ Warn → amber, else → red.
Optional text shown under the indicator: Good / Warn / Bad. Leave blank to show just the value.
Static text for context — no queries run. Supports headers, bold/italic, lists, links, and code spans.
Lat/Lng: first two columns are latitude + longitude; third is label, fourth is the metric.
Runs alongside the main query on every refresh; delta shows current vs this value.
If set, a download icon appears on the widget. Clicking it runs this query and downloads the results as a CSV file.
Add group
Groups with the same page render together in presenter mode. Skip numbers to leave gaps for future groups; gaps are ignored at runtime.
Overrides the widget title font-size for all widgets in this group. Useful for boards displayed on big TVs.
Group still shows on the dashboard but is skipped in the kiosk. Ungrouped widgets are always hidden from presenter mode.
Packs widgets top-to-bottom instead of left-to-right. Use this when you want narrow widgets to stack vertically next to a map/chart even if the grid has room to fit them side-by-side.
Copy group
Copies the group, its widgets, and (optionally) its group filters. Widget alert rules and snapshot history are not copied — those are runtime state and may not belong on the target board.
Add R script
Save query
Board settings
How often MySQL queries actually run, regardless of how frequently users poll. All users share this minimum — if the snapshot is fresher than this, polls return cached data instantly.
Tight (60px)
Standard (100px)
Generous (140px)
px (40–400)
Add board
Add user
Edit user
Dashboard
Presentation mode
Add board
Add external URL
Dashboard
Enter your username or email and we'll send you a reset link.
No saved queries yet. Run a query and click ⊕ Save to save it.
R Script library
No saved R scripts yet.
Admin
Users
Username
Email
Role
Board
Last login
Boards
Board
Members
Widgets
Min recompute
API key (global)
Notification channels
— where alerts get delivered (Slack webhook or email)
Name
Type
Target
Enabled
Threshold rules
— per-widget conditions that fire a channel on each ok→firing transition
Widget
Condition
Channel
State
Last fired
Recent firings
— last 100 alert evaluations that crossed into firing
Time
Widget
Value
Threshold
Channel
Delivered
Query timeout
— how long a MySQL query is allowed to run before being killed
The server kills any single SELECT that exceeds this many seconds. The default is set by the MYSQL_QUERY_TIMEOUT env var (currently —s). Raise it here if widgets are consistently timing out. Per-widget overrides can be set in the widget editor (global admins only).
Server caches
— flush after editing a filter template, CPM rules, or any widget SQL referenced by these caches
The server caches two heavy reads. Filtered-snap caches widget results per filter-value combination so repeated filter clicks are instant. CPM eligible stores caches the latest-row-per-store scan of fraznetapp_cpm for the {{cpm_eligible_stores}}/{{cpm_latest}} tokens. Both refill on the next request after a flush.
HubSpot API connection
— Private App token used by Python widgets
Paste a HubSpot Service Key token (or legacy Private App token). Widgets running Python get it as the HUBSPOT_TOKEN environment variable.
Step-by-step setup ↗
HubSpot query library
— reusable Python snippets users can drop into widgets
Name
Description
Updated
HubSpot dashboards (PNG snapshots)
— snapshot URLs you can drop into Presenter mode
Label
Dashboard ID
Last snapshot
Pages
Dark mode
Kiosk URL
Other external dashboards (Genesys, Salesforce, generic)
— snapshot URLs you can drop into Presenter mode
Label
Kind
Last snapshot
Pages
Dark mode
Kiosk URL
After adding a source you need to seed its login session once: python bootstrap_session.py --source <source_id> on your local machine, then scp the resulting JSON to the server path shown.
Add widget
Stat
Gauge
Line chart
Bar (time)
Progress
Badges
Cache table
R Script
Status light
Funnel
Histogram
Calendar heatmap
Category bars
Grouped chart
Result table
Pie / Donut
Map
API
Note
⅛
¼
⅓
½
¾
Full
½ row
1 row
2 rows
3 rows
4 rows
Left
Center
HubSpot library:
Chart history builds up over each poll cycle.
Optional format per row: Label | SQL | format — e.g. integer, currency, currency_gbp, percent_raw.
Lines starting with --- become full-width section headers (e.g. --- This Week).
Vertical ▐
Horizontal ▬
Useful in kiosk mode where hovering for tooltips isn't possible.
Toggle the inline labels (region names on the map, slice values on charts, etc.). Tooltips and the colour fill stay regardless.
Path should resolve to a single value
Pie
Donut
Show
Hide
A fixed number or a single-value SQL query. The gauge fills proportionally from 0 to this target. The "Query / Script" above is the current value.
Two-column result: label, value. Order rows in the query — the first row is the top of the funnel.
One-column result: a numeric observation per row. The first column is used if more than one is returned.
How many equal-width buckets to split [min, max] into. 2–100.
For "Higher is better": value ≥ Good → green, ≥ Warn → amber, else → red. For "Lower is better": ≤ Good → green, ≤ Warn → amber, else → red.
Optional text shown under the indicator: Good / Warn / Bad. Leave blank to show just the value.
Static text for context — no queries run. Supports headers, bold/italic, lists, links, and code spans.
Lat/Lng: first two columns are latitude + longitude; third is label, fourth is the metric.
Runs alongside the main query on every refresh; delta shows current vs this value.
If set, a download icon appears on the widget. Clicking it runs this query and downloads the results as a CSV file.
Add group
Groups with the same page render together in presenter mode. Skip numbers to leave gaps for future groups; gaps are ignored at runtime.
Overrides the widget title font-size for all widgets in this group. Useful for boards displayed on big TVs.
Group still shows on the dashboard but is skipped in the kiosk. Ungrouped widgets are always hidden from presenter mode.
Packs widgets top-to-bottom instead of left-to-right. Use this when you want narrow widgets to stack vertically next to a map/chart even if the grid has room to fit them side-by-side.
Copy group
Copies the group, its widgets, and (optionally) its group filters. Widget alert rules and snapshot history are not copied — those are runtime state and may not belong on the target board.
Add R script
Save query
Board settings
How often MySQL queries actually run, regardless of how frequently users poll. All users share this minimum — if the snapshot is fresher than this, polls return cached data instantly.
Tight (60px)
Standard (100px)
Generous (140px)
px (40–400)
Add board
Add user
Edit user
Dashboard
Presentation mode
Filters
Filters apply to every widget in this group whose SQL contains the placeholder token. Widgets without the token show N/A when the filter is active.
Date range placeholders: {start} / {end} — user input, empty when blank {start_or_min} — start, or 1000-01-01 when blank (use for "before X" support) {end_or_max} — end, or 9999-12-31 when blank (use for "after X" support)
Example template covering range, before, after, and unbounded: c.date >= '{start_or_min}' AND c.date <= '{end_or_max}'
Set a new password
Your account is using the default password. Choose a new one before continuing.
Add notification channel
Add alert rule
Add HubSpot query
Add HubSpot dashboard
Refresh login session
This source's login session needs to be refreshed. Since SSO / 2FA / email-code prompts
can't be completed by the headless snapper on the server, you need to run a one-time
bootstrap on your laptop. Firefox opens, you sign in manually, the resulting session JSON
gets copied to the server, and the next snap uses the fresh login.
Source:
Kind:
URL:
Session file on server:
One-click bootstrap
Launches PowerShell on your laptop and runs the bootstrap automatically — no command paste needed. Requires the frazil-bootstrap:// URL handler to be installed once (see below).