← Files HoneycombARCHIVED FILE
references/board-layout.md
6.54 KB · Sep 30, 2026 · 22:51 UTC
# Board Layout Reference
## The panels array
`create_board` takes a single `panels` array. Each panel must have a `type` field:
| type | Required fields | Optional fields |
|------|----------------|-----------------|
| `"query"` | `type`, `id` (query run PK like `QR-abc123`) | `name`, `description`, `chart_type`, `display_style`, `size` |
| `"slo"` | `type`, `id` (SLO PK) | `size` |
| `"text"` | `type`, `content` (Markdown, max 10000 chars) | `size` |
Panels appear on the board in the order listed. Order matters — put the most important context first.
## Grid system
The board uses a **12-column grid**. Panels wrap to the next row when total width exceeds 12.
Use `size: { "width": N, "height": N }` to control each panel:
- `width`: 1–12 columns (default fills available space)
- `height`: rows (default varies by panel type)
### Layout examples
**Stat row** — three stats side-by-side at the top:
```json
[
{ "type": "query", "id": "QR-...", "name": "Request Rate", "chart_type": "stat", "size": { "width": 4 } },
{ "type": "query", "id": "QR-...", "name": "Error Rate", "chart_type": "stat", "size": { "width": 4 } },
{ "type": "query", "id": "QR-...", "name": "P95 Latency", "chart_type": "stat", "size": { "width": 4 } }
]
```
**Full-width heatmap**:
```json
[{ "type": "query", "id": "QR-...", "name": "Latency Distribution", "size": { "width": 12, "height": 3 } }]
```
**Two graphs side-by-side**:
```json
[
{ "type": "query", "id": "QR-...", "name": "Request Rate", "size": { "width": 6 } },
{ "type": "query", "id": "QR-...", "name": "Error Rate", "size": { "width": 6 } }
]
```
**SLO widget beside a summary graph**:
```json
[
{ "type": "slo", "id": "SLO-...", "size": { "width": 4 } },
{ "type": "query", "id": "QR-...", "size": { "width": 8 } }
]
```
There's no one right layout. Design it to tell a story — context at the top, most important signals next, breakdowns below.
### Recommended layout from top to bottom
#### Row 1: Introduction — text panel + primary SLO
Place a text panel (width 8). If there is a primary SLO, place it alongside (width 4). The text panel should describe the board's purpose, link to relevant code or docs, and note what to watch for.
```
┌──── text (8) ─────┬── SLO (4) ──┐
```
#### Row 2: Other SLOs at 1/3 width
If there are additional relevant SLOs, place them in a row at width 4 each (up to 3 across).
```
├── SLO (4) ──┬── SLO (4) ──┬── SLO (4) ──┤
```
#### Row 3: Stat panels at 1/4 width
Key single-number metrics (P95 latency, error rate %, request count, unique users) work well as `chart_type: "stat"` at width 3, fitting 4 across.
```
├─ stat (3) ─┬─ stat (3) ─┬─ stat (3) ─┬─ stat (3) ─┤
```
#### Remaining rows: Queries with explanatory text
For the main query panels, use width 6 (two across) or width 12 (full width).
For particularly interesting or non-obvious queries, add a narrow text panel (width 3-4) next to the query (width 8-9) on the same row. Use the text panel to explain what to look for, what normal looks like, or what actions to take if values change.
```
├── text (3) ──┬──── query (9) ────────────┤
├──── query (6) ─────┬──── query (6) ──────┤
```
Not every query needs an explanatory text panel — just the ones where the meaning isn't obvious from the name alone, or where there's useful context about thresholds or expected behavior.
### Height tips
- Keep heights consistent within a row for visual alignment
- SLO panels work well at height 4
- Stat panels work well at height 4
- Simple chart-only query panels work at height 4
- Query panels with two graphs and `display_style: "chart"` need height 7
- For queries with `display_style: "combo"`, if they have no breakdowns, add 1 to height.
- For queries with `display_style: "combo"` and a breakdown, add 3-5 height units, depending on how many rows the table needs.
- Text panels for row headers work at height 1; explanatory text panels next to queries should match the query panel height
- Heatmap panels work at height 5
## Chart types
| value | Description |
|-------|-------------|
| `"default"` | Honeycomb chooses (correct for heatmaps; use when unsure) |
| `"none"` | Table only |
| `"line"` | Line chart |
| `"stacked"` | Stacked area chart |
| `"bar"` | Bar timeseries |
| `"stat"` | Single value / stat panel |
| `"categorical_bar"` | Categorical bar chart |
| `"pie"` | Pie chart |
Guidance:
- `"default"` for heatmaps — do not override this
- `"stat"` for single-number highlights (error rate %, unique users, P95 value)
- `"line"` for time-series comparisons and trends
- `"pie"` or `"categorical_bar"` for categorized breakdowns
- When there's a GROUP BY, `"combo"` display style shows both graph and table
## Display styles
| value | Description |
|-------|-------------|
| `"chart"` | Visualization only (tool default) |
| `"table"` | Data table only |
| `"combo"` | Both chart and table |
Use `"combo"` when there's a GROUP BY / breakdown — you want to see both the graph and the ranked table. Use `"chart"` for clean time series. Stat panels (`chart_type: "stat"`) pair with `"chart"` display.
## Preset filters
`preset_filters` creates interactive dropdown controls on the board — viewers can filter all graphs by a column value without editing queries. Maximum 5.
```json
{
"preset_filters": [
{ "column": "http.route", "alias": "Route" },
{ "column": "app.region", "alias": "Region" },
{ "column": "app.account_tier", "alias": "Account Tier" }
]
}
```
Good candidates: route, region, account tier, deployment version, user type. Especially useful for boards shared across teams or used during incidents. If the service has meaningful segmentation columns, suggest preset filters.
## Tags
```json
{ "tags": ["team:platform", "tier:critical"] }
```
Use `list_boards` to see existing tags and follow those formats.
**Format rules:**
- **Keys**: lowercase letters only, max 32 chars, no hyphens
- **Values**: start with lowercase, can contain letters/numbers/`-`/`/`, max 128 chars
- ❌ WRONG: `"user-facing:true"` (hyphen in key)
- ✅ RIGHT: `"userfacing:true"`, `"tier:critical"`
## Duplicate query trick
Honeycomb rejects duplicate queries on a board. To show the same data in two formats (e.g., stat + line), add a trivially-true filter to one of them — for example `service.name exists`. Results are identical but the queries are technically different.
Keep the timeframe consistent between both panels so the numbers agree.
SHA-256: 500999223e53a6e5bc616063f2d859828a2b42bae14c763f1e815b317a458c9a