Honest trade-offs so you can pick the right tool for your project.
Around 15KB minified (~5KB gzip) including the reactive runtime from @preact/signals-core. No other dependencies.
The default entry point uses a recursive descent parser — no eval(), no new Function(). Works in strict CSP environments without unsafe-eval.
Pure ESM. Drop a <script> tag or import as a module. No bundler, no compiler, no CLI.
Powered by @preact/signals-core. Only the exact DOM nodes that depend on a changed signal are updated — no re-rendering, no diffing.
All js-* attributes are stripped from the DOM after binding. The HTML you ship to users is clean.
Write interactivity in HTML attributes. No JavaScript required for simple use cases with defer init.
Nested js-scope elements form a prototype chain. Children inherit parent state; local changes don't pollute parent scope.
Module architecture lets bundlers tree-shake unused directives and the CSP-safe parser when using the unsafe entry point.
The CSP-safe parser doesn't support destructuring or multi-statement blocks. Complex logic should live in methods on your scope object. The signet-unsafe.js entry point accepts full JavaScript via new Function() if needed.
Signet.js has no component model or slots. You can compose behaviors with nested scopes and custom directives, but it's not a replacement for component-based frameworks.
Single-page application routing is out of scope. Signet.js works per-page, not across navigations.
There is no dedicated hydration mode for server-rendered HTML. Mounting replaces children in js-if/js-for blocks.
js-for re-creates all DOM nodes on every list change when the array length changes, and reuses nodes via in-place signal updates when it stays the same. No keyed diffing.
Compared to Alpine.js or petite-vue, there are fewer community plugins, examples, and integrations. This is a young library.
| Feature | Signet.js | Alpine.js | petite-vue | HTMX | Stimulus |
|---|---|---|---|---|---|
| Bundle size | ~5KB gz | ~40KB (min+gz) | ~6KB | ~14KB | ~11KB |
| Reactivity | Signals | Proxy (Vue-like) | Proxy (Vue core) | Server-driven AJAX | DOM mutation callbacks |
| CSP-safe | ✓ (default) | ✗ (uses eval) | ✗ (uses Function) | ✓ | ✓ |
| No build step | ✓ | ✓ | ✓ | ✓ | Bundler recommended |
| Component model | ✗ | ✓ (x-component) | Limited | ✗ | ✓ (Controllers) |
| Transitions / animation | ✗ | ✓ (x-transition) | ✓ (v-show + CSS) | CSS only | CSS only |
| Template syntax | js-* attrs |
x-* attrs |
v-* attrs |
hx-* attrs |
data-* attrs + JS |
| Server integration | None | None | None | ✓ (core feature) | None |
| TypeScript types | ✓ (JSDoc) | ✓ | ✓ | ✓ | ✓ |
| Ecosystem maturity | New (2026) | Mature | Mature | Mature | Mature |
Signals mean only the exact DOM nodes that need an update are touched. No re-rendering, no dirty-checking, no full component re-evaluation.
Government sites, banking apps, enterprise intranets — anywhere unsafe-eval is forbidden. Signet.js default entry is the only HTML-directive library that works out of the box.
Drop <script src="signet.js" defer init> in the <head>. Add js-scope to your HTML. You're done.
E-commerce pages, landing pages, email-captured web views. Every kilobyte costs conversions. Signet.js + signals-core totals ~3KB.
The entire source is <1000 lines of readable ESM. You can read it all in an afternoon. No magic, no abstractions hiding what's happening.
Use React, Solid, Svelte, or Vue. Signet.js has no component model, no router, and no state management beyond flat reactive scopes.
Alpine.js's x-transition and Vue's transition system are excellent. Signet.js defers this to CSS.
HTMX is purpose-built for that. Signet.js manages local client-side state; it doesn't fetch HTML from a server.
Alpine.js has hundreds of plugins, Mastodon/Twitter communities, and years of Stack Overflow answers. Signet.js is new.
Alpine.js is the most direct competitor. Both add directives to HTML and avoid a build step. The key differences:
eval() for expressions (requires CSP unsafe-eval). Signet.js does not.$store, $dispatch, $watch), and a plugin system. Signet.js is minimal.petite-vue is Vue's official lightweight drop-in. It uses the same v-* syntax as Vue 3:
new Function()). Not CSP-safe.v-scope).HTMX and Signet.js are complementary, not competing:
Stimulus takes a more structured, class-based approach: