honest framework

honest-page

The page is a declared set of surfaces, and every reference it emits resolves at the gate — no button wired to nowhere.

You know a Jinja base template with blocks. honest-page is the host contract — surfaces, the HTMX and honest-DOM bootstrap — with HC-REF checking every hx-target reaches a route.

Every page in the app is assembled a little differently. One template puts the notification zone in the header, another forgets it. One wires the HTMX bootstrap, another loads it in a different order and the state collection runs before the DOM is ready. A button posts to /orders/submti — a typo — and the page renders green, because nothing checks that the action target it emits actually reaches a route. The page looks fine until someone clicks the dead button.

honest-page is the contract for what an honest-framework HTML page must be: a declared set of surfaces, slots, and wiring conventions that every application provides, so the point where a typed server request becomes a rendered page — and a user interaction becomes a typed request again — is the same shape everywhere.

A page is a declared set of surfaces

honest-page defines the required surfaces (header, main, footer, and the notification zones), the HTMX and honest-DOM bootstrap sequence, the application state manifest, and the server-side context the template expects. It is not a layout engine and not a component: it is the host contract that lets honest-type, honest-DOM, and honest-alerts visibly connect. Any implementation that satisfies the contract can host the framework's modules.

Every reference the page emits resolves

The rule that makes a page trustworthy: every reference a rendered surface *emits* (an hx-* action target, a {% include %}) must resolve to something that exists — a mounted route or a real template — checked statically at the gate. Asserting the HTML contains the right string proves nothing about whether the string points at anything. honest-check's HC-REF rules resolve each one. The dead button — the hx-post to a route no one mounted, the typo'd target — is caught before render, not discovered in the browser.

Why the resolved page is a poka-yoke

An emitted reference that points at nothing is invisible to every test that checks output strings: it renders, it reports green, and it does nothing when clicked. That is a category of bug, not a stray mistake: any hand-written target can name a route that isn't there. Require every emitted reference to resolve at the gate and the category closes. A page cannot ship a control wired to nowhere, because the wire that reaches nowhere stops the gate. Visual design, theming, and navigation structure stay the application's to choose; the contract governs only that the page's connections are real.