Skip to content

Latest commit

 

History

History
150 lines (116 loc) · 7.57 KB

File metadata and controls

150 lines (116 loc) · 7.57 KB

sprae

DOM microhydration

Reactive sprinkles for HTML/JSX

```html
```

Principles

HTML-native : Keep existing HTML.
Standard JS expressions.
No build step, no config.

Open & pluggable : Controllable state. ESM-first.
Signals-powered reactivity.
Sandboxed. CSP-safe eval.

5kb, 0 deps : One <script> tag or npm i.
Any backend, any template, +JSX.
No ecosystem lock-in.

Usage

CDN ESM
Add one script tag. Sprae evaluates `:` attributes and makes reactivity. ```html <script src="//unpkg.com/sprae" data-start></script> ```

Variants:

<!-- CSP-safe (no eval) -->
<script src="//unpkg.com/sprae/dist/sprae-csp.umd.js" data-start></script>

<!-- Preact signals -->
<script src="//unpkg.com/sprae/dist/sprae-preact.umd.js" data-start></script>

Install or download sprae.js and import:

<script type="module">
  import sprae from './sprae.js'

  const state = sprae(document.getElementById('app'), { count: 0 })
  state.count++ // updates DOM
</script>

Variants: sprae-csp.js (CSP-safe), sprae-preact.js (preact signals).

Reference Docs →

Directives 18 Modifiers 14
directive description example
:text Set text content <span :text="name">
:html Set innerHTML <div :html="content">
:class Set classes <div :class="{active: true}">
:style Set styles <div :style="{color:'#fff'}">
:value Bind input (state→DOM) <input :value="text">
:change Write input back (DOM→state) <input :change="v => text = v">
:<prop> Set any attribute <a :href="url">
:hidden Toggle visibility <div :hidden="!show">
:if :else Conditional render <div :if="cond">
:each List render <li :each="item in list">
:scope Create local state <div :scope="{x:1}">
:ref Element reference <input :ref="name">
:mount Connect/cleanup hook <canvas :mount="el => init(el)">
:intersect Visibility observer <img :intersect.once="load()">
:resize Size observer <div :resize="({width}) => ...">
:fx Side effect <div :fx="log(x)">
:on<event> Event listener <button :onclick="fn()">
:portal Move to container <div :portal="'#modals'">
modifier description example
.debounce Delay until activity stops :oninput.debounce-300
.throttle Limit call frequency :onscroll.throttle-100
.delay Delay each call :onmouseenter.delay-500
.once Run only once :onclick.once
.window Listen on window :onkeydown.window
.document Listen on document :onclick.document
.body .root .parent Other targets :onclick.parent
.self Only direct target :onclick.self
.away Click outside element :onclick.away
.prevent Prevent default :onclick.prevent
.stop Stop propagation :onclick.stop
.passive .capture Listener options :onscroll.passive
.enter .esc .tab .space Common keys :onkeydown.enter
.ctrl .shift .alt .meta Modifier keys :onkeydown.ctrl-s
.arrow .digit .letter .delete Key groups :onkeydown.digit

What is it? : A ~5kb script that adds reactivity to HTML via :attribute="expression". No build step, no new syntax — just HTML and JS you already know.

When to use it? : Adding interactivity to server-rendered pages, static sites, prototypes, or anywhere a full framework is overkill. Works with any backend — Rails, Django, PHP, Jekyll, Next.js.

How does it compare? : 3x lighter than Alpine, faster in benchmarks. Signals-powered (emerging standard). Full comparison.

Components? : Use define-element for declarative web components, or any CE library.

Is it production-ready? : 3+ years, 12 major versions. Used by a few SaaS systems and landing pages. Full TypeScript support.