Agustin Robledo

Fullstack developer and photographer

Log viewer

2026

  • deployments
  • observability

Streaming

State

The log is a Next.js build on a hosting platform, generated line by line with the pace a real one has: a clone, a cached install with two deprecation warnings, a long pause while it compiles, an ESLint warning about an <img>, and then page generation, which is where the volume is. Streaming plays it live, with bursts of two hundred lines a second. Ready is the same build finished, Failed ends in a type error with its code frame, and Truncated is a build that passed the host's 4 MB limit, so the viewer holds its first fifty-odd thousand lines and says so on the last row.

Fifty thousand lines is nothing to a scroll bar and too much for the DOM, so only the rows in view exist, plus a few above and below. Every line is one row of a fixed height, which means any line's position is a multiplication, and the rows above and below the window are two spacers. The lines themselves live outside React in an append-only array, parsed once when they arrive, and a frame of the stream appends whatever is due and publishes once. Rendering per line would never keep up at that rate.

Following is the part that decides whether a live log is usable. The rule is that the viewport follows while it is at the bottom and stops the moment you scroll up. Telling my own pinning from your scroll turned out to be simple: pinning always lands at the bottom, so a scroll event that is anywhere else can only be yours. A button then floats over the bottom of the log with the count of lines that arrived since you stopped, and either it or scrolling back down resumes. It overlays the log instead of taking a row, so nothing you are reading moves.

Warnings and errors get a faint tint, their own icon and a colour, and the toolbar counts them. An error that runs over several lines in a row counts once, so clicking the count steps from one error to the next instead of through the lines of the same message. Errors are red and warnings yellow, two colours added to the palette for this and tuned to sit with its indigo and lime; the icon is there so colour is never the only cue. ANSI colour codes from pnpm and Next are parsed into spans, and a secret the build echoed shows as a redacted chip, the way hosting platforms mask them.

Clicking a line number copies a link ending in #L12, and Shift-clicking a second one copies the range as #L6-L9, the format code hosts use. On this page the hash goes into the address bar, and opening a link with one highlights those lines and scrolls to them, waiting for them to arrive if the build is still streaming. On the home grid the same click copies the absolute link here and leaves the address alone.

Search runs a plain substring check over every line's text, which is fast enough to stay under a keystroke even at fifty thousand lines, and new lines are checked as they stream in so the count keeps up. Enter and Shift+Enter walk the matches and centre each one. The log is a single tab stop; the arrows move a line cursor inside it and Enter copies its link, so the whole thing works without a mouse and without turning the gutter into thousands of buttons in the tab order.

Keyboard and access

Keyboard
The toolbar buttons and the search field are ordinary tab stops, and the log itself is one more. Inside the log the up and down arrows move an active line, Shift with the arrows extends a selection from it, Page Up and Page Down move by a screen, Home goes to the first line and End to the last, which also resumes following while the build is streaming. Enter copies the link to the active line or the selected range, Escape clears both. The error and warning counts are buttons: each press steps to the next one and shows its position, and Shift-click steps back. E and Shift+E do the same for errors, or warnings when the build has no errors, and / or Cmd+F while focus is inside the card moves to the search field. In that field Enter goes to the next match, Shift+Enter to the previous one and Escape clears it. Clicking a line number copies its link, and Shift-clicking another copies the range between them. While streaming, scrolling up pauses following and a button at the bottom of the log says how many lines arrived since; it or scrolling back to the bottom resumes.
Screen readers
The status is a word next to its coloured dot, never colour alone, and each warning or error starts with an icon labelled Warning or Error, on its first line when it runs over several. The log is a region named Build log with its line count. Lines are not a live region, since a stream can add two hundred a second; a polite live region reads the status when it changes, the active line as the arrows move, the match number and line after Enter in the search field, the error number and line when stepping through errors, each copied link, and, while paused, how many new lines are waiting, at most once every few seconds. Redacted secrets read as the text REDACTED.
Reduced motion
With reduced motion the stream still pins to the bottom with no smooth scrolling, jumps to a match or an error land at once, the new lines button and the copied notice appear without a transition and the streaming dot holds still.