Skip to content

Repository files navigation

HyperStandard Main Image

HyperStandard

Fast. Interactive. Web Interface.


Open in StackBlitzNPM versionNPM package minimized gzipped size

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.



Getting Started

npm create hstd my-app
cd my-app
npm install
npm run dev

Use --ts for TypeScript with @hstd/ts IntelliSense:

npm create hstd my-app --ts

Install

Scaffold with Vite

npm create hstd my-app

NPM

npm i @hstd/std

HTTP

import{$,hashtml}from"https://hstd.io";

ImportMap

{
"imports": {
"@hstd/std": "https://hstd.io"
}
}

Examples

Class-model

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> `}

Interactive binding

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> `}

Post-processing

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);});})}

Works with Async Iterator

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();

Reactive Arrays

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.

Template Literal Pointer

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.

Property Bundle Reference

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.

Derived Pointers

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).

Runtime Validation

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/contenteditable

Packages

HyperStandard 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/html tagged templates
  • CSS property completion after css. and inside [css]: { }
  • DOM event completion after on. and inside [on]: { }
  • IO property completion after io.
  • $.this property completion with sibling property suggestions
  • Static diagnostics for type mismatches, position mismatches, and invalid io element targets
// tsconfig.json
{
"compilerOptions": {
"plugins": [{ "name": "@hstd/ts" }]
}
}

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/ts

Syntax Highlighting

TextMate grammars (VS Code, Sublime Text) and Tree-sitter queries (neovim, Helix, Zed) are available in pkg/vscode and pkg/tree-sitter-hstd.

License

hstd is MIT licensed.

About

HyperStandard - Fast. Interactive. Web Interface.

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages