Rendering in Sinuous is handled by hyperscript like function calls.

HTMLElement = h(tag|Component|Fragment, [props?, text?, Element?, Observable?,...])

Luckily we don't have to worry about that too much because of the fantastic htm package.

This module converts native JS tagged template literals to h function calls. Sinuous supports both runtime and compile time transformation with sinuous/htm and sinuous/babel-plugin-htm respectively.

The compile time version is preferred in production as the HTM runtime (0.5kB) will not be included, improves gzip compression and the performance cost of parsing the HTML will be removed.

A Simple Example

import { html } from 'sinuous';
const element = html`
<h1>Hello world!</h1>

This returns a real HTML element that can be appended to the DOM.
The example is translated to the following h call under the hood.

const element = h('h1', 'Hello world!');


Observables are the key mechanisms to make the views of Sinuous reactive. They can represent state as content or properties in the view. Simple state can be represented in the view as a single template expression.

const property = o('box');
const content = o('This is some text.');
const p = html`
<p class=${property}>

If there is need for a computation in the view, one thing to keep in mind is that to retrieve the value of an observable a function call is needed and the computation is wrapped in a closure. Let's take a look.

const length = o(0);
const div = html`
<div>${length} squared: ${() => Math.pow(length(), 2)}</div>

Try it on Codesandbox


Note that Sinuous sets properties on the DOM element object, not attributes on the HTML element. This makes for better consistency across browsers and a nicer API for booleans. There are some gotchas, however. Attributes such as colspan are camel cased to colSpan, and for on the label element is htmlFor to avoid collision with the language keyword.

html`<a href=></a>`;


If an attribute starts with on and is a function, then it will be registered as an event listener.

<a href="#" onclick=${() => alert('you are 1,000,000th visitor!')}>
Click here to win a prize


If an attribute has a style property, then that will be handled specially. It accepts either an object or a string.

<h1 style=${{ 'font-family': 'Comic Sans', color: 'springgreen' }}>
Happy Birthday!