Layout
A grid is defined by two plain-text files: layout, a box drawing of the dashboard, and mapping, which binds each box to a plot.
AI assisted, human approved — novem uses AI to review and keep our documentation up to date.
A grid has exactly two content files, both written as plain text
(Content-Type: text/plain):
layout— the geometry: which panels exist and how big they are.mapping— the content: which plot goes in each panel.
Writing either file re-parses both, so they can be updated independently and
in any order. The parsed result is available as JSON under the grid's
json/data.json (structure) and json/meta_data.json (mapping refs).
The layout file
The layout is a rectangle drawn with three characters: +, - and |.
Boxes are split into smaller boxes by divider lines, and each innermost box
holds one instruction naming the plot label to show there:
+-------------+----------+
| | |
| {A:-} | {B:-} |
| | |
| | |
| | |
+-------------+----------+
The rules:
- One outer frame. The whole drawing is one rectangle; blank rows and columns around it are ignored.
- Dividers split a box in two (or more). A divider is a full row of
-/+(horizontal split) or a full column of|/+(vertical split) running edge to edge inside a box. A divider can't mix-and|. - A pipe-ended horizontal divider floats.
|---------|creates a floating vertical stack. Its ASCII heights remain the default allocation, but a renderer may redistribute unused height between the stack's children. Boundary-connected+---------+dividers stay fixed and are resolved first, so floating stacks nest inside the fixed layout. The parsed wrapper is marked with"floating": true; fixed wrappers omit the field. - Splits nest. Each sub-box can be divided again, alternating directions as needed. Any rectangular arrangement is expressible.
- Size is proportional. The distance between a box's border characters becomes its share of the rendered dashboard. Shared divider characters have no size of their own. In the example above the left panel spans 14 of 25 horizontal units, so it gets 56% of the width.
- One instruction per box. Whatever remains in an innermost box after
removing drawing characters and whitespace must be a single
{LABEL}instruction.
Instructions
{LABEL[:POSITION]}
LABEL— an alphanumeric label (A,B2,perf, …) defined in the mapping file. A label with no matching mapping line leaves the cell empty.POSITION— an optional vertical anchor for the cell's content:
| Position | Meaning |
|---|---|
^ | top |
- | middle (default) |
v | bottom |
{A}, {A:} and {A:-} are equivalent. Any other position character makes
the instruction invalid and the cell renders empty. In a fixed cell, position
anchors content within its allocation. In a floating stack, it also tells the
renderer where the content should stay when sibling heights are redistributed.
The mapping file
The mapping file binds layout labels to plots, one binding per line:
LABEL => REFERENCE[,PARAM=VALUE]...
For example:
A => /u/novem_demo/p/nei_rgn_perf,c=f
B => https://novem.io/u/novem_demo/p/nei_rgn_tb,c=t,h=f,m=d,s=2,tbg=f
LABEL— the label used in the layout file.REFERENCE— a plot shortname or path. The equivalent forms/p/my_plot,p/my_plot,/u/you/p/my_plot,u/you/p/my_plot, andhttps://novem.io/u/you/p/my_plotare all accepted.- Comma options are the preferred form because they are concise and easy to
type, for example
/u/you/p/my_plot,m=d,s=2. - Standard query parameters are also accepted, so a working Novem URL such as
/u/you/p/my_plot?m=d&scale=2can be pasted directly into a mapping. If both forms set the same option, the later comma option wins. Whitespace anywhere on the line is ignored, and lines without a=>are skipped.
Parameters
| Parameter | Alias | Values | Default | Description |
|---|---|---|---|---|
include_header | h | t, true, f, false | false | Include the plot's header in the cell |
include_caption | c | t, true, f, false | false | Include the plot's caption in the cell |
mode | m | l, light, d, dark | inherit | Render this cell in light or dark mode |
scale | s | 1, 2, 3 | consumer default | Set the device or raster scale factor |
transparent_background | tbg | t, true, f, false | consumer default | Request a transparent or filled background |
An unrecognised value falls back to the parameter's default. The preferred
comma form uses the compact s=2 alias and stores it as scale: 2. Query
strings should use /i's canonical scale=2 spelling because /i reserves
s for legacy image-size codes.
These are per-cell editorial controls, like the options on a
{{ vis }} section in a document
or e-mail. If m, scale or tbg is omitted, the field is left out of
metadata so a TV, renderer or other consumer can inherit its surrounding
context.
Note: if the same label appears on several mapping lines, the last line wins. Labels that exist in the mapping but not in the layout are simply unused.
Reading the parsed result
After a successful write the parsed layout is exposed on the grid's JSON endpoints, useful for debugging a layout that doesn't split the way you expected:
curl -H "Authorization: Bearer $NOVEM_TOKEN" \
https://api.novem.io/v1/vis/grids/my_dashboard/json/data.json
{
"structure": {
"type": "wrapper",
"width": 25,
"height": 6,
"children": [
{
"type": "wrapper container",
"width": 14,
"height": 6,
"children": [],
"inst": { "lid": "NL--hwckacar", "position": "middle", "include_header": false, "include_caption": false }
},
{
"type": "wrapper container",
"width": 11,
"height": 6,
"children": [],
"inst": { "lid": "NL--tguxadkh", "position": "middle", "include_header": false, "include_caption": true }
}
]
}
}
The lid values are internal link ids connecting each cell to its mapping
entry. json/meta_data.json lists them alongside the labels and normalized
per-cell presentation options:
curl -H "Authorization: Bearer $NOVEM_TOKEN" \
https://api.novem.io/v1/vis/grids/my_dashboard/json/meta_data.json
{
"refs": [
{
"label": "B",
"lid": "NL--tguxadkh",
"include_header": false,
"include_caption": true,
"mode": "dark",
"scale": 2,
"transparent_background": false
}
]
}
See also
- Grid API — every grid endpoint.
- API overview — verbs, permissions and the filesystem metaphor.