{% set page_title = 'Links' %}
{% include '_header.html' %}
{#- The shared toolbox (ADR-0030). Not documentation and not a runbook — a
subject's runbook lives on the check that watches it — but the two or three
dashboards and tools somebody mid-incident wants *now*, without hunting
through a wiki. So: a launcher. One flat level of groups flowed into columns,
each entry a mark and a title, curated order preserved exactly as written.
Everything on it comes from the deployment's own `config/links.yaml`; this
file owns only how it looks. -#}
{%- macro icon_mark(link) -%}
{#- A brand logo does not theme: a black mark vanishes on the dark themes and
a white one on the light. So an icon that declared a **pair** emits both
files and CSS hides one — the choice cannot be made here, because under
the `auto` theme the server does not know what the OS will resolve to.
Anything else — one file, a favicon — rides a **theme-invariant light
chip**, which is what keeps a single-file mark legible in every theme, and
one image serves both backgrounds: a second would be the same bytes fetched
twice. The chip is the floor, the pair is the upgrade (ADR-0030 §4).
Which images, and where each is from, is `LinksConfig.mark_for`'s answer,
because the page's own Content-Security-Policy is taken from the same one:
an image with a `url` is fetched from elsewhere — a remote mark, or the
entry's site favicon — and one without is ours, by the entry's name. -#}
{%- set mark = links_config.mark_for(link) -%}
{%- endmacro -%}
{#- The setup guide, folded (ADR-0030). With no links the page used to be the
guide in full — a sample file, where it goes, the roster of installed marks,
how to add one — more than a screen before anybody had a link; and a
deployment that had written its file lost the roster with the empty state. So
the guide is two folds, each the browser's own disclosure and closed, which
works without script: *Add links* on a page that has none, and *Icon names*
there and at the foot of a page that has links.
A fold is a card, whose surface Bootstrap paints. What its summary adds beside
its name is muted from our own token for that reason: `.text-muted` is an ink
nobody here measured on that surface (`tests/test_contrast.py`). -#}
{%- macro fold(name, aside) -%}
{{ name }} · {{ aside }}
icon: takes a name, never a URL — a
dozen entries for one tool cost one mark, one fetch, one
probe. These names are already installed. Each is drawn
twice, once for a light background and once for a dark
one, and the page picks by theme:
| name | on light | on dark |
|---|---|---|
{{ name }} |
{%- for variant, side in (('on-light', 'light'), ('on-dark', 'dark')) %}
|
{%- endfor %}
To use a mark of your own, put an icons/
directory beside links.yaml and drop the file
in: firewall.svg is the name
firewall. Name it after one of the installed
marks and it replaces that one. A pair —
firewall-on-light.svg and
firewall-on-dark.svg — is one name with a
drawing for each background; a single file rides a light
chip instead, so it stays legible under every theme.
{{ failure.name }} did not answer:
{{ failure.verdict.detail }} ({{ failure.verdict.url }},
checked {{ failure.verdict.checked_at | since }})No links yet. This page is the deployment's toolbox, the dashboards and tools to have at hand in an incident, and it has not been filled in.
{%- call fold('Add links', "one file in this deployment's configuration") %}Links come from this deployment's own configuration — one flat level of groups, each with an ordered list of entries:
groups:
- title: Toolbox
links:
- title: Grafana
url: https://grafana.example.org/
icon: grafana
Put that in {{ links_file }} and reload — the
file is re-read when it changes, so nothing needs
restarting.
Nothing matches. Esc clears the filter.