htmlctl / Category Page

Extensions let htmlctl stay for agents without turning into a framework.

The core `htmlctl` model is intentionally narrow: publish direct website assets quickly, preview exact artifacts, and promote without drift. Extensions exist for the cases where a static site needs dynamic behavior, but that behavior should not drag the whole publishing stack toward application-framework complexity.

Thin

Keep the core publishing path small

Routed

Dynamic services sit behind explicit prefixes

Validated

Compatibility checked before cutover

Why extensions exist

A website sometimes needs more than static assets. The mistake is letting that redefine the whole system.

The common failure mode

Once a site needs something dynamic, many stacks collapse into full application thinking. Suddenly every content update and layout change inherits the cost of a framework, server runtime, and developer ceremony that mostly exists for humans building apps, not agents publishing websites.

The htmlctl answer

Keep the publishing core optimized for agents and move dynamic behavior into optional companion services. Route those services through explicit backend prefixes, validate compatibility before cutover, and treat them as runtime add-ons rather than as a reason to rebuild the whole system around an app framework.

What an extension model should preserve

The important thing is not just adding features. It is protecting the publishing model.

Separation

Dynamic logic stays out of the asset pipeline

Site assets are still rendered and published as site assets. The extension runtime lives separately and is exposed only through declared paths such as /newsletter/*.

Compatibility

Cutovers are checked explicitly

The extension contract declares compatibility requirements, and operators can validate them before routing traffic. That keeps extension onboarding operational instead of ad hoc.

Environment scope

Runtime state stays per environment

Backends, ports, auth, and extension listeners remain staging or prod concerns. They do not get baked into the promoted artifact.

Rollback clarity

Static releases and dynamic services stay legible

If a site rollout and an extension rollout are different operations, you can reason about failure, rollback, and recovery much more cleanly.

Agent fit

The core stays optimized for direct asset publishing

Agents keep working against HTML, CSS, JavaScript, metadata, and assets directly instead of being forced through framework structure that exists for a different development model.

Optionality

Not every site needs dynamic features

Extensions are there when the site needs them. They do not burden every website by default.

How the model works

The operational path is simple on purpose.

1

Run the extension as its own service

Bind it locally, give it its own env, secrets, and database, and keep it outside the core static deploy path.

2

Validate compatibility and add a backend route

Check the extension contract and route a path such as /newsletter/* to the extension listener for that environment.

3

Keep site publishing and runtime rollout separate

Static site changes can still move through preview and promote. Extension runtime changes remain operational cutovers you can verify independently.

Next step

See the concrete example.

The newsletter extension is the clearest demonstration of why this model exists and why it is better than bloating the publishing core into an application framework.