dira decision memory for AI coding agents
$dira whydec-0012
int-0002Zero-ceremony operation — one binary, no server, no daemonactive 2026-07-29
dec-0012Surfaces are server-rendered Go templates and static output — no SPA, no dira-operated hostaccepted 2026-07-30
✗ An embedded static SPA served from the binary, as design.md §9 originally specifiedThree problems, and the first is fatal to the growth engine.
✗ A hosted renderer at dira.sire.rundesign.md §9 sketches this as Tier 3 "much later", and dec-0005 already rejected dira-operated infrastructure for sync on ops-burden grounds — no ops, no on-call, no security surface for a solo maintainer already carrying kazi.
✗ Ship both — static output now, hosted laterDesigning two serving paths before either is validated.
int-0002Zero-ceremony operation — one binary, no server, no daemon
dec-0012Surfaces are server-rendered Go templates and static output — no SPA, no dira-operated host
✗An embedded static SPA served from the binary, as design.md §9 originally specified
✗A hosted renderer at dira.sire.run
✗Ship both — static output now, hosted later
dec-0012 ◆ accepted 2026-07-30

Arising from int-0002 — Zero-ceremony operation — one binary, no server, no daemon

Surfaces are server-rendered Go templates and static output — no SPA, no dira-operated host

Two questions, one answer, because they share a reasoning core: **nothing dira renders requires a client runtime or a server dira operates.**

`dira ui` — server-rendered templates, not an SPA

Go `html/template` + `embed.FS`, served from the binary on localhost. JavaScript only as progressive enhancement, and only on `/distill` where disposition benefits from keyboard handling. Every page must render and be usable with JS disabled.

This is not a preference. The design that already exists *is* server-renderable: the three screens in `docs/design/screens/` were built with zero JavaScript, and the `.chain-stack` mobile variant is a CSS media query rather than a component swap. An SPA would add a runtime and a JSON API layer to serve markup that is already static — and it would break the one channel the growth loop depends on.

The public renderer — `dira render`, deployed by the user

`dira render` emits static HTML the user pushes wherever they already publish, GitHub Pages being the obvious default since `dec-0005` already established GitHub as the infrastructure the user brings.

**This makes `cst-0004` structural rather than aspirational.** The constraint says dira must never require a network service or hosted tier. With no dira-operated host in the picture, that is not a promise anyone has to keep — there is nothing to require. The audience most likely to check this claim is the audience being pitched.

Consequences worth stating

- **Crawlability is an acceptance criterion, not a nice-to-have.** A rendered decision page must be readable by a client that executes no JavaScript. That is testable and E6 should test it. - **No JSON API is built for the UI.** If one appears later it is for third parties, which is a different decision with a different justification. - **`dec-0005`'s storage interface is untouched.** This narrows how surfaces are *served*; reads still go through the interface, and the `github` backend in E7 is unaffected. - **The hosted tier is not forbidden, only unnecessary.** `dec-0007` still permits a team tier; if it arrives it renders the same templates server-side. The static path extends into a hosted one; the reverse would have required rework.

Alternatives on record — 3

✗An embedded static SPA served from the binary, as design.md §9 originally specifiedrefused Three problems, and the first is fatal to the growth engine.

The rendered decision pages are the long-tail SEO surface named in .agents/product-marketing.md §7 channel 4 — "every rendered decision page is a page answering why did project X choose Y" — and client-side rendering makes them uncrawlable, so the SPA actively undercuts dec-0010. Second, the three built screens in docs/design/screens/ contain zero JavaScript, so an SPA is a runtime added for nothing already designed. Third, on localhost the data is already in-process, so a JSON API layer exists only to serialise to yourself.

revisit ifa surface appears that genuinely needs client-side state — a graph explorer with live filtering, not a document view

✗A hosted renderer at dira.sire.runrefused design.md §9 sketches this as Tier 3 "much later", and dec-0005 already rejected dira-operated infrastructure for sync on ops-burden grounds — no ops, no on-call, no security surface for a solo maintainer already carrying kazi.

That reasoning transfers intact to rendering. It would also make cst-0004 a promise that has to be kept rather than a property of the architecture.

revisit ifteams pull for zero-setup shared rendering, per dec-0007's team tier

✗Ship both — static output now, hosted laterrefused Designing two serving paths before either is validated.

The static path is strictly more constrained, so it can be extended into a hosted one later without rework; the reverse is not true.

Every decision in this repo is recorded like this one.

Keep your own →