A map of the whole page, for the corner beside it. A machined groove holds the page drawn small, a glass loupe rides over the part in the window, and the page’s section headings are printed beside the groove at their own height, the one you are reading lit. Drag the loupe or press the groove to move; the headings are links.
Fixes the slow query on db-2 that took the first canary out. p95 is back under 200 ms.
4.2
Canary gates can hold on errors as well as latency. The deploy board shows every region on one line.
Signing keys can be revoked from the console.
The audit log exports to cold storage every night.
4.1
Release notes go to the team by email when a release is live everywhere.
4.2.1
Fixes the slow query on db-2 that took the first canary out. p95 is back under 200 ms.
4.2
Canary gates can hold on errors as well as latency. The deploy board shows every region on one line.
Signing keys can be revoked from the console.
The audit log exports to cold storage every night.
4.1
Release notes go to the team by email when a release is live everywhere.
Release notes
When this runs
Lode takes a canary out by itself when p95 latency passes 800 ms for three minutes, or when errors pass one per cent of requests. This runbook is for the person on call when that happens.
The first five minutes
Look at the deploy board. The canary shows red and the release is held.
Open the canary’s dashboard and note the minute it rolled back.
Say in the releases channel that the canary is out and that you are on it.
Find the cause
Most rollbacks in the last year came from one of three places: a slow query, a cache that went cold, or a service outside Lode that timed out. Start with the database and list the slowest queries of the last quarter of an hour:
lode db top --host db-2 --since 15m --by p95
If one query is far slower than the rest, it is almost always the cause. The release notes say which change added it.
Ship the fix
Cut a patch release from the release branch, not from main, so nothing else goes out with it. The canary takes five per cent of traffic, then 25, then all of it, one region at a time.
lode release cut --from release/4.2 --patch
lode canary start --steps 5,25,100
Afterwards
Write two lines in the incident log: what rolled back and what fixed it. If the same cause comes back within a month, it gets a ticket of its own.
A narrow groove · --pl-rail
02
Every state, at once
Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.
The corner: its label and how far through the page you are, the groove with the page drawn on its floor, and the page’s section headings beside it.
for
attribute
an id
What it maps. An article that scrolls with the window, or a box that scrolls on its own, which it then follows instead.
label
attribute
text
Printed over the groove and given to the list of headings. On this page, by default.
offset
attribute
px
The height of a bar that sticks over the page, so the loupe covers what is really in view.
media
attribute
a selector
What else to draw as a box, besides code and pictures: a demo, a table, a card.
heads
attribute
a selector
Which headings name the sections. Every h2 with an id, by default, but not one in a dialog.
.tui-page-loupe__marks
class
built
The headings, as links, each at its own height and pushed down where two would touch, a leader drawn back up to where it belongs.
aria-current="location"
attribute
on a heading
The section being read: its heading lit, with the green lamp beside it.
--pl-rail
custom property
length
The groove’s width: 72px, and 60px in a narrower corner.
--progress
custom property
0 to 1
How far through the page the reader is, written on the element for anything of yours that wants it.
refresh()
method
none
Draw the map again now. It does so by itself whenever the page or the corner changes size.
pageLoupeMarks · pageLoupeAt · pageLoupeCurrent
function
kit.mjs
The rules, pure: where each heading’s label goes, how far through the page the window is, and which section is being read. The groove and the loupe use the Loupe scroll’s own.
04
Markup
<article id="article">
<h2 id="runs">When this runs</h2>
<p>…</p>
<h2 id="first">The first five minutes</h2>
…
</article>
<aside class="corner">
<tui-page-loupe for="article" label="On this page" offset="64"></tui-page-loupe>
</aside>
import '/kit/kit.mjs'; // defines <tui-page-loupe>
// It redraws itself when the page or its corner changes size.
// Drew the page again in place, with new content? Ask it to look again:
document.querySelector('tui-page-loupe').refresh();
// Only some headings name your sections? Say which:
// <tui-page-loupe for="article" heads=":scope > section > h2">
The headings are a list of links, named by the label, so the keyboard and a screen reader reach every section from the corner.
The section being read is marked with aria-current="location", so it is said as well as lit.
The groove and the loupe are a picture and a pointer’s shortcut, as a scrollbar is: hidden from assistive technology and out of the tab order, and there is nothing on them that scrolling does not reach.
The percentage beside the label is for the eye only; the page’s own scrolling already tells a screen reader where it is.
A press on the groove glides to its place; with reduced motion it jumps.
Without the script there is no corner; the docs keep a list of sections in the page itself for that, and for narrow screens.
06
How it’s built
It is the Loupe scroll’s rail, pointed outwards. The map is the page’s own line boxes: for each block a Range round its contents gives one client rect for every run of text, and loupeLines joins each line’s runs into one bar, scaled down the groove to fit the whole page and across it to fit the line. Code, pictures and whatever media names are boxes; a part of the page that is sticky, a demo held beside the text, is left off, because it is not on the page’s run. loupeWindow places the glass over what the window shows, less the offset of a sticky bar, and its lens holds a copy of the map scaled 1.4 times about the loupe’s middle. The headings are placed by pageLoupeMarks, and pageLoupeCurrent lights the last one to pass a line a third of the way down the window. A ResizeObserver on the page and the groove redraws the map, and refresh() finds the page again by its id after it is drawn in place.
07
Rules
page-loupe.rules.mdIn the brain
For a long page read from the top down, in a corner that stays beside it.
5 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.
A scroll area whose scrollbar is a map of what it holds. A narrow machined rail runs beside the text with every line drawn small on its floor, headings darker and code as a box. A glass loupe rides over the part in view and shows it a little magnified. Drag the loupe to scroll, or press the rail to jump there; underneath it is a native scroll container.
A region that scrolls, with its scrollbar made as a machined rail: a groove cut into the plate and a thumb like a fader cap riding in it. Scrolling itself is the browser’s own.
Pagination as a thumbwheel. A knurled wheel stands in a recess with a window in its face, and the page number rolls past it on a paper tape. A key either side steps by one. The keys are plain links, so it pages without any script; the wheel is what a script adds.