SEHTML only has one HTML attribute — do="..." that can replace vanilla JS
and wires up the click handler, the fetch call, the animation, whatever you asked for.
No build step to try it. No JS to write for a toggle button.
<button do="when clicked, toggle #hero-panel">
I had to write alot of vanilla JS repeatedly for even simple things like a button, showing/hiding panels, anims, etc... Eventually that got old...
So instead of just dealing with it, I wrote THIS! It reads a sentence out of a do attribute. Things like when clicked, toggle #panel — and does the wiring itself! Adds the event listener, resolves the target element, runs the action. That's the whole idea. It's not trying to replace the big ones like htmx, react, etc... Mainly because it can't but it here to make your days better with less strain!
Just one <script> tag and every do attribute on the page becomes active. Good for prototypes, static pages, etc.
Run npx sehtml build index.html and it compiles every instruction to plain JS
Each of these is a real, working do="" phrase. copy any line straight into an attribute.
toggle #panel
Also show and hide. Works on this, an #id, or a .class.
fade in #modal
Fade, slide, grow, shrink — chain them with then for a sequence.
add class 'active' to #tab
State management without touching classList yourself.
fetch '/api' show result in #list
GET or POST, with an optional loading bar and result target.
if value is a valid email show #ok
Length, format, ranges, custom regex. checked on input, no library.
save this as 'draft'
Backed by localStorage. Load it back with load 'draft' into #field.
scroll to #pricing
Plus go to, open in a new tab, refresh page.
count up #views to 5000 over 2 seconds
Eased number animation. Good for the stat you're proud of.
when items are reordered, save the new order as 'ranking'
Native drag-and-drop, saved automatically.
Every demo below is running the actual SEHTML runtime.
when typed in after 300ms,
if value is a valid email show #validate-ok
otherwise hide #validate-ok
when scrolled into view,
count up #counter to 1000 over 3 seconds
when clicked, copy #copy-target to clipboard
then show #copy-toast for 2 seconds then hide #copy-toast
when typed in, save this as 'note'
when this loads, load 'note' into this
Same behavior. This is the actual line count.
| Vanilla JS | SEHTML |
|---|---|
const btn = document.querySelector('#btn');
const panel = document.querySelector('#panel');
btn.addEventListener('click', () => {
if (panel.style.display === 'none') {
panel.style.display = '';
} else {
panel.style.display = 'none';
}
});
|
<button do="when clicked,
toggle #panel">
|
| 9 lines, 2 queries, 1 listener, 1 conditional | 1 attribute |
These toggle open the same way everything else on this page works — do="when clicked, toggle #x".
Add the runtime — either via npm, or a plain script tag if you don't want a build step.
npm install sehtml # — or, zero build step — <script src="https://unpkg.com/sehtml/dist-live/sehtml-live.js"></script>
Write your first instruction on any element.
<button do="when clicked, toggle #my-panel">Click me</button> <div id="my-panel" style="display:none">Hello, SEHTML!</div>
When you're ready to ship, compile it down to plain JS — no parser in your production bundle.
npx sehtml build index.html --out dist