Making the data cascade visible
Garp merges template data from three levels — global files in data/, a directory's _data.yaml, and page frontmatter, last one wins. It's a simple cascade, but it was garp's only invisible state: when a template renders the wrong title, the answer to "which layer set this?" lived in your head.
Now it's on screen. garp dev ships a toolbar — a "g" button in the corner of every page it serves — and clicking it opens a panel showing the current page's resolved data, every key labeled with the layer that won it: frontmatter, the directory's _data.yaml, a data/* global, or config.yaml. Below that, the page's layout chain (following each template's extends) and the collections the page belongs to.
The part I care most about is what building it didn't touch. The panel's backend answers GET /_garp/page?path=… by recomputing the cascade on demand — reusing the build's own functions, with zero changes to any engine file. The UI is ~190 lines of vanilla JavaScript that also absorbed the dev server's live reload, so development injects exactly one script tag into pages it serves.
And that script tag is injected into HTTP responses only. The site/ directory on disk stays byte-identical — there's a test guarding that invariant. Garp's rule is that the tooling must vanish from what ships; a dev convenience that leaked into the output would break the one promise the whole tool is built on. The toolbar exists at exactly one layer: while you're developing, on your machine, and nowhere else.