Skip to content

zeixcom/le-truc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

263 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Le Truc

Type-safe reactive Web Components — HTML-first, backend-agnostic

Le Truc adds a thin reactive layer to server-rendered HTML. You keep your existing backend (Java, PHP, Python, C#, static site generator — anything that outputs HTML). Le Truc wires fine-grained DOM updates to reactive component properties in the browser, without re-rendering whole subtrees and without requiring JavaScript on the server.

The result is SolidJS-style reactivity packaged as standard Custom Elements: components are reusable across projects, type-safe, and carry no framework lock-in.

Why

Digital agencies building content-rich sites face a recurring choice: imperative JavaScript that becomes unmaintainable as complexity grows, or a SPA framework that takes over rendering and requires a JavaScript backend. Neither is a good fit when the backend is a CMS and the initial HTML is already correct.

Le Truc solves the specific problem of stateful interactivity on server-rendered pages:

  • The server renders HTML — Le Truc never re-renders it
  • Reactive properties update only the DOM nodes that actually changed
  • Components are plain Custom Elements — they work in any host environment
  • TypeScript catches integration errors at compile time

Installation

npm install @zeix/le-truc
# or
bun add @zeix/le-truc

Quick Start

  1. Start with your server-rendered HTML:
<basic-hello>
  <label for="name">Your name</label>
  <input id="name" name="name" type="text" autocomplete="given-name" />
  <p>Hello, <output for="name">World</output>!</p>
</basic-hello>
  1. Define the component:
import { bindText, defineComponent } from '@zeix/le-truc'

defineComponent(
  'basic-hello',                     // Component name (must contain a hyphen)
  ({ expose, first, on, watch }) => { // Factory: query DOM, declare props, return effects
    const input = first('input', 'Needed to enter the name.')
    const output = first('output', 'Needed to display the name.')
    const fallback = output.textContent || ''

    expose({ name: output.textContent ?? '' }) // declare reactive prop

    return [
      on(input, 'input', () => ({ name: input.value || fallback })),
      watch('name', bindText(output)),
    ]
  },
)
  1. Import the module and watch it work.

defineComponent registers the element via customElements.define(). expose() declares reactive properties, watch() wires up DOM updates that fire only when the tracked signal actually changes, on() binds event listeners.

Documentation

Full documentation with live examples is at zeixcom.github.io/le-truc:

Key Features

  • 🧱 HTML-first — enhances server-rendered markup; no Virtual DOM, no hydration
  • 🚦 Reactive properties — signals with automatic dependency tracking and fine-grained updates
  • ⚡️ Pinpoint effects — only the exact DOM nodes that changed are touched
  • 🧩 Composable — build behaviour from small, reusable parsers and effect functions
  • 🌐 Context support — share state across components without prop drilling
  • 🪶 Tiny — ≤10 kB gzipped, tree-shakeable
  • 🛡️ Type-safe — full TypeScript inference from selector strings to property types

Le Truc uses Cause & Effect for its reactive primitives.

Contributing & License

Contributions, bug reports, and suggestions are welcome — see CONTRIBUTING.md.

License: MIT — © 2026 Zeix AG

About

Le Truc - the thing for type-safe reactive web components

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors