The Flag Was Set and Nothing Shipped
Written later and filed to this date, as part of filling in every day of the year.
The way to look at a draft used to be to lie to the build. A piece sits in the content directory with draft: true in its header, and nothing on the site will render, list, feed or link it. To see it as it would publish, layout and metadata and related links included, a reviewer changed that one word to false, started the dev server, read the page, and then remembered to change it back. Every week, for every draft. The remembering is the part that fails. A manual step that must be undone is a step that will one day be left done, and the next push publishes a piece nobody finished.
The preview replaced the lie with a lock that needs two keys. One environment variable, set by a person at the command line, and one condition only the build tool can supply: the process must be the dev server. A production build with the variable set stays locked. The dev server without the variable stays locked. Plain Node, which has no notion of a dev server, reads as locked. The predicate lives in one module, and nine places that used to filter drafts each in their own words now ask that module. A source contract walks every page and fails if any of them mentions the draft field by hand, so a tenth place cannot drift.
The proof is the half worth copying. The accessibility suite builds the real site with the preview variable set, on purpose, as the worst case. If the flag alone could unlock a build, that build would carry the injected draft fixture; the test asserts nothing draft-shaped is in it. Beside it, an integration test starts a real dev server with the flag on, fetches both fixtures and expects a full page with sentinel text for each, then asks for a slug that does not exist and expects nothing. All of it was watched red first: delete the dev-server condition and three unit tests fail; inline one call site’s filter and both contract tests fail.
The preview turned out to guard something it was never designed for. The build compiles a draft but never renders one, so a draft whose body would throw at render time leaves the build green. The dev server renders it. When a stray expression in a sibling repository’s lesson format took the whole site down, the regression test for the fix went on the preview path, on a draft fixture carrying the same expression, because the preview is the only place a draft is rendered before it is real.
The draft preview, then: drafts render only under the dev server, only with an explicit opt-in, and the production build runs with that opt-in set to prove it ships none. The header stays true, and seeing the page costs one command instead of a promise to remember.