Every { } bakes into HTML.
Chocola compiles enhanced HTML, CSS, and JS straight to the browser. Write logic as HTML, not template strings — no bundler, no virtual DOM, three dependencies total.
<p>Status: {status}</p>
<div if="{status === 'live'}">
<span>● Online</span>
</div>
<p>
Status: <span>live</span>
</p>
<div>
<span>● Online</span>
</div>
// title, status: baked once at build time
if's and logic — as elements, not templates
Chocola reads control flow the way it reads everything else: as HTML. No template language to learn, no curly-brace soup to escape — just attributes, and a tag that disappears when it's done its job.
<div if="{user.role
===
'admin'}">Admin Panel</div>
<div elif="{user.role
===
'editor'}">Editor Dashboard</div>
<div else>View
Only</div>
<void if={isLoaded}>
<h1>Data Loaded</h1>
<p>Here is your content.</p>
</void>
A recipe, and the thing it made from it
A component file is a blueprint, not an instance. Chocola clones and type-checks its state for every place the component is used, then hands you a single mount hook to wire up the rest.
import body from "./html/my-button.html";
import styles from "./css/my-button.css";
// runs once, when this instance mounts
function RUNTIME(self, ctx) {
const btn = self.querySelector("btn");
btn.addEventListener("click", () => {
ctx.cta = true;
});
}
export default function MyButton() {
return {
body,
styles,
script: RUNTIME
}
}
The enhanced HTML this component renders — logic blocks, static { },
and live
${ } included.
The state shape, declared once with types (Boolean, String…). Every instance gets its own typed, cloned copy.
The component's root element, passed into RUNTIME — query it
directly,
no
refs system needed.
A mount hook, not a render loop. It runs once per instance; the template reacts to ctx on its own.
The public surface for this component — methods and properties any outside script can call on a live instance.
Four versions, shipped one at a time
Chocola grows the same way it compiles: deliberately, with nothing added until the layer underneath is solid.
Foundations
- Single-page SSG
- Basic logic blocks
- Components
Consolidation
- CSR SPA router
- Single file components
- Declarative imports for components
- ESM modules and dependencies
Reactivity
- Reactivity engine
- Live
${foo}bindings - Reactive state and lifecycle hooks
- Fine-tuning optimization options
Shipping
- SSR SPA
Install once. Compile forever.
No boilerplate. No plugins to reconcile. Point Chocola at a folder.