Legend Configuration Persistence
Graph view legend configuration (colors per node type, title templates, color rules, and line styles and arrows per relationship) is saved in backlog/databases/graph-legends.yaml inside the project, versioned with git. Previously it only existed in browser local storage, so switching browsers, devices, or clearing cache would lose it, and different team members would see the same graph differently. The coloring of Cypher query blocks (view: graph) in documents even depended on the reader's browser rather than the project itself.
What the Configuration File Looks Like
A single YAML file, grouped by database name:
default:
captionsVisible: true
types:
Person:
caption: "{{name}}"
color: "#204af3"
rules: []
relations:
WORKS_AT:
dash: solid
arrow: end
color: "#0ef19a"
hidden: []
Block-style YAML with LF line endings, easy to review, diff, and edit by hand. Missing fields or broken rules do not crash the interface—reading falls back gracefully.
Four Entry Points, One File
| Entry Point | Usage |
|---|---|
| Legend settings panel | Gear button opens it; changes preview instantly and are written on save |
| CLI | backlog graph legend get <database> (default human-readable summary, --json outputs raw JSON) / set <database> <file> (--stdin reads from standard input) / remove <database> (idempotent) |
| MCP | graph_legend_get / graph_legend_set / graph_legend_remove tools; agents do not need to edit files by hand |
| Manual editing | Edit the YAML directly with an editor |
All four paths read and write the same file; changes made anywhere are visible everywhere else.
Startup Recovery and Local Cache
When the browser opens, it first renders using the local cache (zero delay, offline-capable), then fetches the project file from the server:
- If the project has a configuration and it differs from local → use the project version and write it back to local cache.
- If the project does not have one but local does → upload the local configuration once to complete migration; the old configuration is not lost.
- If neither has one → keep the default coloring.
On save, it writes locally first (takes effect immediately) and then writes to the file; if the file write fails, the operation is not interrupted, the local copy is kept, and migration is retried automatically next time the page opens. Behavior is consistent with the pure-local-cache era when the server is unreachable.
Cross-Tab and Out-of-Band Hot Updates
After a legend save, an update is broadcast, and other open tabs of the same project apply it immediately. When the file is modified externally via CLI, MCP, or an editor, the server's file watcher converts the change into the same broadcast—no page refresh needed.
A true change refreshes only once: rewrites with identical content (including only field-order adjustments) do not trigger any refresh; deleting an entry that did not exist is also a silent no-op.
Automatic Colors Are Recorded in the File
On save, colors currently actually drawn for types without an explicit color are written into the file, so the file records the complete picture the viewer sees, rather than leaving it to be re-derived from type names on each open. Clicking the color of a type back to "×" in the panel restores automatic coloring.
Conflict Strategy
Concurrent writes to the same configuration use last-writer-wins, without merging—legend is a low-frequency, single-person configuration. File writes are atomic (temporary file + rename), so no half-written file is left behind.