HyperStandard
import{$,hashtml,on}from"hstd"constComponent=()=>{constcount=$(0);returnhtml`<h1>Count is ${count}</h1><button${{[on.click]: ()=>count.$++}}> Add more!</button> `;}document.body[html]=Component();hstd = HyperStandard is a minimal JavaScript library to build fast, interactive, extensible web interface. Visit live demo.
npm create hstd my-app
cd my-app
npm install
npm run devUse --ts for TypeScript with @hstd/ts IntelliSense:
npm create hstd my-app --tsnpm create hstd my-appnpm i @hstd/stdimport{$,hashtml}from"https://hstd.io";{
"imports": {
"@hstd/std": "https://hstd.io"
}
}import{$,hashtml,on,css}from"@hstd/std"constbuttonClass=$((alertText)=>({[css]: {color: "white",backgroundColor: "blue",},[on.click]: ()=>alert(alertText)}))constMain=()=>{constcount=$(0);returnhtml`<button${{[on.click]: ()=>count.$++,[buttonClass]: "hi"}}> I'm styled ${count}!</button> `}import{$,hashtml,io}from"@hstd/std"constLinked=()=>{constvalueHolder=$(0)returnhtml`<h1>these are linked!</h1><input${{[io.value]: valueHolder,type: "range"}}><input${{[io.value]: valueHolder,type: "range"}}><label>value is ${valueHolder}</label> `}constCanvas=()=>{constcolorSwitch=$(true);returnhtml`<canvas${{id: "color",[on.click]: ()=>colorSwitch.switch()}}></canvas> `.on(({ color })=>{constctx=color.getContext("2d");colorSwitch.into($=>$ ? "red" : "blue").watch($=>{ctx.fillStyle=$;ctx.fillRect(0,0,100,100);});})}import{$,hashtml,io}from"@hstd/std";constIterated=asyncfunction*(){constuser=$(''),{ promise, resolve }=Promise.withResolvers();yieldhtml`<label>Show user <input${{[io.value]: user}}/></label><button${{[on.click]: resolve}}>submit</button> `;awaitpromise;yieldhtml`<label>Loading...</label> `;const{ name, age, link }=awaitfetch(`/api/user/${user.$}`).then(res=>res.json());yieldhtml`<div><label>${name}</label><label>${age}</label><label>${link}</label></div> `;}document.body[html]=Iterated();import{$,hashtml,on,io}from"@hstd/std"constTodoApp=()=>{consttodos=$(["Buy milk","Walk dog"]);constinput=$('');returnhtml`<ul>${todos.into(item=>html`<li>${item}</li>`)}</ul><input${{[io.value]: input}}><button${{[on.click]: ()=>{todos.push(input.$);input.$='';}}}> Add</button> `}$([...]) creates an ArrayPointer that tracks mutations (push, pop, shift, unshift, splice, sort, reverse, swap, set) and updates the DOM automatically. Derived queries like find, includes, some, every, reduce return reactive Pointers.
import{$,hashtml,css}from"@hstd/std"constAnimated=()=>{constrotation=$(0);constscale=$(1);consttransform=$`rotate(${rotation}deg) scale(${scale})`;returnhtml`<div${{[css.transform]: transform}}>Hello</div> `}$`...` creates a Pointer that interpolates reactive values into a string. When any interpolated Pointer changes, the string updates automatically.
import{$,hashtml,css}from"@hstd/std"constThemed=()=>{constprimary=$("royalblue");returnhtml`<div${{[css]: {backgroundColor: primary,color: $.this.backgroundColor,borderColor: $.this.color,border: "2px solid",}}}> color follows backgroundColor</div> `}$.this.propertyName creates a DeferredPointer that references another property within the same attribute object. The reference is resolved at render time.
import{$,hashtml,io}from"@hstd/std"constDashboard=()=>{constquery=$('');constdebounced=query.timeout(300);conststatus=debounced.into(q=>q ? `Searching: ${q}` : "Type to search");returnhtml`<input${{[io.value]: query,placeholder: "Search..."}}><p>${status}</p> `}Pointers support chained derivations: .into(fn), .not(), .bool(), .isit(ifTrue, ifFalse), .timeout(ms), .until(value), .sum(n), .sub(n), .mul(n), .div(n), .mod(n), .is(v), .seq(v), .or(v), .and(v).
hstd validates bindings at runtime and throws descriptive errors for common mistakes:
// Position mismatchhtml`<div>${{color: "red"}}</div>`// Error: Object literal in body positionhtml`<div${"hello"}>text</div>`// Error: string in attribute position// Type mismatchhtml`<div${{[on.click]: "str"}}>...`// Error: on.click requires a functionhtml`<div${{[css.color]: ()=>{}}}>…`// Error: css.color requires a string, number, or Pointerhtml`<input${{[io.value]: "str"}}>…`// Error: io.value requires a Pointer// Element mismatchhtml`<div${{[io.value]: ptr}}>…`// Error: io requires input/textarea/select/contenteditableHyperStandard standard library — reactive primitives ($, Pointer, ArrayPointer), DOM templating (h), and declarative bindings (on, css, io).
TypeScript language service plugin for HyperStandard. Editor-agnostic IntelliSense that works with VS Code, vim, neovim, Helix, Zed, and any TypeScript-compatible editor:
- HTML element completion inside
h/htmltagged templates - CSS property completion after
css.and inside[css]: { } - DOM event completion after
on.and inside[on]: { } - IO property completion after
io. $.thisproperty completion with sibling property suggestions- Static diagnostics for type mismatches, position mismatches, and invalid
ioelement targets
HyperStandard-to-WebComponents adapter.
Scaffold a Vite + HyperStandard project with function components, css bindings, HMR, and light/dark theme support.
npm create hstd my-app # JavaScript
npm create hstd my-app --ts # TypeScript + @hstd/tsTextMate grammars (VS Code, Sublime Text) and Tree-sitter queries (neovim, Helix, Zed) are available in pkg/vscode and pkg/tree-sitter-hstd.
hstd is MIT licensed.