More vesta examples.

Copy a command, compare the source data, then check the simulated board before publishing.

Simple inputs

Start with plain text or a small JSON object when you want the board to read like a status line.

Wrapped textflagshiptext.json

Plain text wraps across as many rows as it needs and centers itself. Good for announcements, reminders, and message-of-the-day boards.

$ vesta render --input testdata/text.json
testdata/text.json
"the quick brown fox jumps over the lazy dog near the riverbank"
Key/value statusflagshipkv.json

Labels sit left, values flush right, one pair per row. Good for operational data where the label matters as much as the value.

$ vesta render --input testdata/kv.json --template kv --valign center
testdata/kv.json
{
  "status": "online",
  "uptime": "14d 3h",
  "temp": "72F",
  "version": "2.4.1"
}

Dense layouts

Use columns and tables when the goal is comparison: weather, scores, rankings, inventory, or any short list.

Two-column dashboardflagshipweather.json

Two key/value pairs per row instead of one, which doubles how many fields fit before the board runs out of rows. No --template needed: --columns 2 on a JSON object makes the default auto template pick the kv layout for you.

$ vesta render --input testdata/weather.json --columns 2 --align center --valign center
testdata/weather.json
{
  "now": "62F",
  "rain_pct": 0,
  "high": "66F",
  "low": "48F"
}
CSV tableflagshiptable.csv

The header line becomes the top row and each following line becomes a board row. CSV is auto-detected, so no --template flag is needed.

$ vesta render --input testdata/table.csv
testdata/table.csv
name,score,rank
alice,98,1
bob,87,2
carol,76,3
dave,61,4
Edge-to-edge tableflagshiptable2.json

--align left (or --align right) spreads the columns across the full width instead of centering them as one block. Alignment then differs by type: text sits flush under its header, numbers sit at the far edge of their column. That is why TIER lines up with TOP, while SCORE sits well to the left of 98.

$ vesta render --input testdata/table2.json --align left
testdata/table2.json
[
  {"name": "alice", "tier": "top", "score": 98, "rank": 1},
  {"name": "bob", "tier": "mid", "score": 87, "rank": 2},
  {"name": "carol", "tier": "mid", "score": 76, "rank": 3},
  {"name": "dave", "tier": "low", "score": 61, "rank": 4}
]

Headers

Titles, subtitles, and separators cost rows, but they can make repeating dashboards easier to scan.

Title and subtitleflagshiphome.json

A title row with colored bookend tiles, plus a subtitle beneath it. Costs two of the six rows, but turns a dense snapshot into a board people recognize at a glance. This example passes a literal subtitle so the preview stays fixed. Use --subtitle time for the current time, or add --24h to render it as 17:00 rather than 5:00P.

$ vesta render --input testdata/home.json --columns 2 --title HOME --title-color green,blue,violet --subtitle 5:00P --subtitle-color violet
testdata/home.json
{
  "temp": "68F",
  "hum_pct": 42,
  "co2": "820",
  "noise": "38db",
  "doors": "shut",
  "light": "on",
  "heat": "off",
  "fans": "on"
}
Rainbow separatorflagshipkv.json

--separator rainbow fills the row below the title block with cycling color tiles. Useful when a board needs a strong section break or a persistent visual identity.

$ vesta render --input testdata/kv.json --template kv --title SYS --separator rainbow
testdata/kv.json
{
  "status": "online",
  "uptime": "14d 3h",
  "temp": "72F",
  "version": "2.4.1"
}
Shifted rainbow separatorflagshipkv.json

--rainbow-offset phase-shifts where the color cycle starts (0-5). Same data and separator as above, just rotated. Useful for keeping repeating boards visually distinct.

$ vesta render --input testdata/kv.json --template kv --title SYS --separator rainbow --rainbow-offset 3
testdata/kv.json
{
  "status": "online",
  "uptime": "14d 3h",
  "temp": "72F",
  "version": "2.4.1"
}

Color and Note

Color carries the signal on these boards rather than decoration, and the Note profile has the least room to spare.

Auto color by field nameflagshipautodetect.json

Fields named with change, delta, or diff get a color tile automatically: green if positive, red if negative, white at zero. No _style is involved here, and --explain confirms it by marking every row auto.

$ vesta render --input testdata/autodetect.json --explain
testdata/autodetect.json
{
  "requests_delta": 128,
  "errors_diff": -12,
  "latency_change": 0
}
--explain output
── color indicators ────────────────────
  REQUESTS DELTA            128   ██ auto
  ERRORS DIFF               -12   ██ auto
  LATENCY CHANGE              0   ██ auto
Signed values and suppressed tilesflagshipbudget.json

"signed" colors a field by its sign even when the name has no change/delta/diff in it. BUDGET is negative so it goes red; SAVINGS is positive so it goes green. "none" does the reverse. SPEND DELTA would auto-color red on its own, but "none" drops the tile and leaves the number untouched.

$ vesta render --input testdata/budget.json --explain
testdata/budget.json
{
  "budget_pct": -8.4,
  "savings_pct": 3.1,
  "spend_delta": -1200,
  "_style": {
    "budget_pct": "signed",
    "savings_pct": "signed",
    "spend_delta": "none"
  }
}
--explain output
── color indicators ────────────────────
  BUDGET                  -8.4%   ██ signed (positive → green, negative → red, zero → white) → bad
  SAVINGS                  3.1%   ██ signed (positive → green, negative → red, zero → white) → good

── numeric formatting ───────────────────
  budget_pct → BUDGET           -8.4 → -8.4%          _pct suffix, label stripped, percent format
  savings_pct → SAVINGS         3.1 → 3.1%            _pct suffix, label stripped, percent format
  spend_delta                   -1200 → -1.2K         auto compaction
Note status boardnotenote_status.json

The Note profile is 3 rows of 15 cells, so every column counts. Keep it to a label, a value, and only the color signal you actually need. A fourth field has nowhere to go. vesta drops it and names it in a warning on stderr, so an extra metric never disappears unnoticed from a scripted board. Both tiles come from narrow ranges rather than a 0-100 scale. --explain shows uptime graded across 95-100 and errors across 0-5, with each zone boundary computed from those bounds. RPS has no _style, so it gets no tile and no indicator line at all.

$ vesta render --input testdata/note_status.json --profile note --explain
testdata/note_status.json
{
  "uptime_pct": 99.97,
  "error_pct": 0.13,
  "rps": 1847,
  "_style": {
    "uptime_pct": {"good": 100, "bad": 95},
    "error_pct": {"good": 0, "bad": 5}
  }
}
--explain output
── color indicators ────────────────────
  UPTIME                 99.97%   ██ range good=100 bad=95   ██≥98.75 · ██97.5–98.75 · ██96.25–97.5 · ██≤96.25
  ERROR                   0.13%   ██ range good=0 bad=5   ██≤1.25 · ██1.25–2.5 · ██2.5–3.75 · ██≥3.75

── numeric formatting ───────────────────
  uptime_pct → UPTIME           99.97 → 99.97%        _pct suffix, label stripped, percent format
  error_pct → ERROR             0.13 → 0.13%          _pct suffix, label stripped, percent format
  rps                           1847 → 1.8K           auto compaction
Range gradientflagshiphealth.json

A _style range object grades a value across four colors instead of picking one, sliding green to yellow to orange to red as it moves from the good end toward the bad end. good and bad name the ends of that scale, not tones, so direction is inferred rather than fixed. The first three fields read good: 0, bad: 100 because less is better. CACHE HIT flips to good: 100, bad: 0, which is why 93% lands green while DISK at 94% lands red.

$ vesta render --input testdata/health.json --explain
testdata/health.json
{
  "mem_pct": 38,
  "cpu_pct": 61,
  "disk_pct": 94,
  "cache_hit_pct": 93,
  "_style": {
    "mem_pct": {"good": 0, "bad": 100},
    "cpu_pct": {"good": 0, "bad": 100},
    "disk_pct": {"good": 0, "bad": 100},
    "cache_hit_pct": {"good": 100, "bad": 0}
  }
}
--explain output
── color indicators ────────────────────
  MEM                       38%   ██ range good=0 bad=100   ██≤25 · ██25–50 · ██50–75 · ██≥75
  CPU                       61%   ██ range good=0 bad=100   ██≤25 · ██25–50 · ██50–75 · ██≥75
  DISK                      94%   ██ range good=0 bad=100   ██≤25 · ██25–50 · ██50–75 · ██≥75
  CACHE HIT                 93%   ██ range good=100 bad=0   ██≥75 · ██50–75 · ██25–50 · ██≤25

── numeric formatting ───────────────────
  mem_pct → MEM                 38 → 38%              _pct suffix, label stripped, percent format
  cpu_pct → CPU                 61 → 61%              _pct suffix, label stripped, percent format
  disk_pct → DISK               94 → 94%              _pct suffix, label stripped, percent format
  cache_hit_pct → CACHE HIT     93 → 93%              _pct suffix, label stripped, percent format
Inline color tilesflagshipcolors.txt

{red}, {green}, and the rest place a tile exactly where you write them in the text. Handy when a message needs explicit tiles instead of semantic styling.

$ vesta render --input testdata/colors.txt --valign center
testdata/colors.txt
{red}{orange}{yellow}{green}
{blue}{violet}{white}{black}{filled}
{colors!}

Beyond render

Every example above uses vesta render, which formats and previews without touching your board. The other three commands read from and write to a real one, and take the same formatting flags.

Explain formatting

Prints the regular preview plus notes about suffix formatting and color tile decisions. Use this when a value or color does not look the way you expected.

$ cat metrics.json | vesta render --explain
Read the current board

Fetches the current board from the Vestaboard Cloud API. Useful before changing a live board or when you want to confirm what is currently displayed. Needs your Cloud read/write key via --token or $VESTABOARD_TOKEN.

$ vesta read-cloud
Publish through Cloud

Sends a finished layout through the Vestaboard Cloud API. This is the normal publish path for most scripts and automations. Uses the same $VESTABOARD_TOKEN as read-cloud.

$ cat data.json | vesta post-cloud --token $VESTABOARD_TOKEN
Publish locally

Sends a finished layout to your own Vestaboard Local API endpoint. Use this only when your script can reach the board on your local network. Takes a separate key, $VESTABOARD_LOCAL_API_KEY, not the Cloud token.

$ cat data.json | vesta post-local --api-key $VESTABOARD_LOCAL_API_KEY
Export character codes

Writes the exact Vestaboard character array instead of a preview. Useful for archiving, debugging API payloads, or handing the rendered output to another tool.

$ cat data.json | vesta render --json-only > saved.json