v2 preview

The sweetest way to build the web

Chocola compiles enhanced HTML, CSS, and JS straight to the browser. Write logic as HTML, not template strings — no bundler, no virtual DOM, only one dependency.

status-badge.html
<h1>{title}</h1>

<p>Status: {status}</p>

<div if="{status === 'live'}">
  <span>● Online</span>
</div>
<h1>Chocola</h1>

<p>
 Status: <span>live</span>
</p>


<div>
  <span>● Online</span>
</div>
2
dependencies
linkedom and acorn, that's it
<1s
building times
blazing fast
0
config files
chocola.config.json is optional
0
bundlers
no Webpack, no Vite; one environment
Logic, baked into HTML

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.

if / elif / else
Chained across sibling elements, resolved like a real conditional.
            

                    <div if="{user.role
                        ===
                        'admin'}">Admin Panel</div>
                    
<div elif="{user.role === 'editor'}">Editor Dashboard</div>
<div else>View Only</div>
<void> wrapper
Renders only its children — the wrapper itself never reaches the DOM.
            

                    <void if={isLoaded}>
                    
  <h1>Data Loaded</h1>
  <p>Here is your content.</p>
</void>
Components

A recipe, and the thing it made from it

A component is a combination of HTML, CSS, and JavaScript logic that gets compiled and rendered into your app automatically.

Greeting.html
                    <script>
                    
 import CoolButton from './CoolButton.html';

 let self;
 let input;

 export let title = "Hello";

 function $runtime() {
  input.focus();
 }
</script>

<template>
 <div>
  <h1>{title}</h1>
  <input bind:self="input" type="text" placeholder="Your name">
  <CoolButton label="Not lame button"></CoolButton>
 </div>
</template>

<style>
 h1 { color: chocolate; }
</style>
<template>

The enhanced HTML this component renders — logic blocks and bindings included

<script>

Props declaration and component logic

<style>

CSS placed inside <style> is automatically scoped to the component — it won't leak out and affect other components.

CLI

One binary. Three commands.

The portable chocola / chjs CLI is the whole toolchain. No chocola.config.json to write, no build scripts to maintain — run it from any folder and sensible defaults kick in.

dev — hot-reload server
# start hacking, defaults to localhost:3000

$ chocola dev

# pick a port, host, and open the browser
$ chjs dev --port 3000 --host localhost --open
build — static output
# src -> dist, components from src/lib

$ chocola build

# override dirs, keep existing output
$ chjs build --srcDir src --outDir dist --libDir lib --no-emptyOutDir
serve — SSR production server
# serve SSR apps, defaults to localhost:8080

$ chocola serve

# custom port, host, and middleware
$ chjs serve --port 8080 --host localhost --middleware ./middleware.js
zero-config

chocola.config.json is optional. Skip it and you get src / dist / lib, dev on :3000, serve on :8080. Add the file — or pass --config / [root] — only when you need more.

zero-boilerplate

User-authored compiler scripts are legacy. chocola dev, chocola build, and chocola serve replace hand-rolled wiring — chjs is the same binary, shorter to type.

Chocola Logo
Get started

Install once. Compile forever.

Zero-config, zero-boilerplate. No chocola.config.json to write, no scripts to maintain — the portable chocola / chjs CLI covers dev, build, and serve.

$ npm i chocola@next { Prompt copied! }
Looking for stable? Use npm i chocola