# Design Rationale

This page collects the *why* behind ChainRender's most important design choices. If you want to understand not
just how the system works but why it was built this way, start here.

## Why fully on-chain, not just "decentralized"?

Because a decentralized backend with a centralized frontend is only half-trustless. The contract can't be changed,
but the website that talks to it can — and that website is what the user actually interacts with. Putting the UI
on-chain makes the *interface* as immutable and verifiable as the contract. The whole point is to remove the last
trusted party: the person hosting your frontend.

## Why content addressing instead of a mutable app registry?

A mutable "current version" pointer is exactly the trust surface we're trying to eliminate. If someone can repoint
an app to new bytes instantly, they can swap it under its users. So immutability is the *floor*, and controlled
mutability is layered on top only where it's provably safe: presentation (zero-gas, doesn't change identity) and
versioning (timelocked, observable, append-only). See **[Content Addressing](../concepts/content-addressing.md)**.

## Why a closed vocabulary instead of arbitrary HTML/JS?

Arbitrary code is unanalyzable, and unanalyzable means unsafe. If an app could embed arbitrary JavaScript, no grade
could be trusted and no action could be verified — the code could do anything. A *closed* vocabulary is the price
of *provable* safety: because every construct is known, the enforcer can prove what an app can and cannot do, and
the grade can be honest. You trade unlimited expressiveness for verifiable trust. For a UI that signs transactions,
that's the right trade.

## Why declared actions instead of raw calldata?

If a button carried arbitrary calldata, a malicious app could hide any transaction behind an innocent label. So
actions are **declared** — a button names its target, selector, and argument shape, and the runtime *constructs*
the calldata from that declaration (`construct-for-sign`). The constructed transaction can *only* be the declared
selector with the declared argument shape. There is no path to smuggle a different call. See
**[Actions & Signing](../concepts/actions.md)**.

## Why a trust *grade* instead of a safe/unsafe badge?

Because trust is a spectrum and honesty demands we show it as one. A binary badge would either be too strict
(flagging safe-but-pinned apps) or too lax (blessing apps with hidden live dependencies). The graded, itemized
approach tells the exact truth: here is the trust cost, here is every reason for it. This reflects the project's
deepest rule — **marketing must never exceed what the code enforces.**

## Why is presentation render-time but content baked?

Because they answer different questions. *How an app looks* (color, spacing, font, size) doesn't change what it
*is* or *does* — so forcing a redeploy (and a new identity) for a cosmetic tweak would be both wasteful and
meaningless. But *what an app says and does* (its text, structure, actions) IS its identity — changing it *should*
produce a new, separately-verifiable version. So: skin is a free render-time parameter; substance is immutable.
This division is what makes ChainRender both trustworthy and pleasant to iterate on. See
**[Theming](../concepts/theming.md)** and **[Versioning](../concepts/versioning.md)**.

## Why ownerless, immutable contracts?

Every registry and renderer in ChainRender is deployed without an owner, admin, or upgrade key. This isn't dogma —
it's the only way the guarantees hold. A registry with an admin is a registry whose admin you must trust. An
upgradeable renderer is a renderer that could change what your app displays. Ownerlessness is what lets a user
verify the system *once* and rely on it *forever*, without trusting any continuing operator.

## The throughline

Every one of these choices trades some convenience for a specific, nameable trust guarantee — and always discloses
the trade honestly. That's the design philosophy in one sentence: **make the trustless thing the default, make
every deviation from it visible, and never claim more than the code enforces.**
