npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@instio/core

v0.1.2

Published

Core DSL for building declarative UI apps in JavaScript — the instio() API, event model, and component builder.

Downloads

314

Readme

@instio/core

The DSL engine for Instio — define UIs and event logic in pure JavaScript.

@instio/core provides the instio() function, the event model, and a renderer-agnostic component builder. It has no DOM dependency — renderers like @instio/svelte consume the compiled output and handle display.


Installation

npm install @instio/core

In the Instio monorepo, link via workspaces:

pnpm install   # from repo root

Quick Start

import { instio } from "@instio/core";

function add(a, b) {
  return Number(a) + Number(b);
}

const app = instio((ui) => {
  const a   = ui.number({ label: "A", value: 0 });
  const b   = ui.number({ label: "B", value: 0 });
  const out = ui.number({ label: "Result", readonly: true });

  ui.button({ label: "Add", variant: "primary" }).click(add, [a, b], [out]);
});

export default app;

Pass the default export to a renderer (e.g. @instio/svelte) to mount it in the browser.


Architecture

instio(fn)
    │
    ├── Builder          accumulates nodes + events
    ├── createUI()       exposes ui.textbox(), ui.row(), …
    ├── ComponentHandle  .click() / .stream() fluent API
    └── State            optional shared reactive state
         │
         ▼
{ tree, events, handlers, state }

| Field | Description | |-------|-------------| | tree | Root node with nested children (layout blocks + components) | | events | Event descriptors (source id, type, input/output node ids) | | handlers | Live { [name]: Function } map — bundled into the browser by the renderer | | state | Root State instance passed to your builder function |


API

instio(builder)

| Parameter | Type | Description | |-----------|------|-------------| | builder | (ui, state) => void | Declares the UI tree and event bindings |

Returns: { tree, events, handlers, state }


UI Components

All factory methods live on the ui object. Each leaf component returns a ComponentHandle for event binding. Layout blocks (row, column) take a callback and optional props.

Currently registered components

These are bootstrapped in src/bootstrapComponents.js:

Inputs

ui.textbox({ label, placeholder, value, lines, max_lines, readonly })
ui.number({ label, value, minimum, maximum, step, precision, readonly })
ui.slider({ label, minimum, maximum, step, value })
ui.dropdown({ label, choices, value, multiselect, allow_custom_value })
ui.checkbox({ label, value })
ui.radio({ label, choices, value })
ui.image({ label, type, sources, height, width })
ui.audio({ label, value })

Outputs & Interactive

ui.markdown({ value, sanitize_html })
ui.chatbot({ label, value, height, show_copy_button })
ui.button({ label, variant, size, icon })   // variant: "primary" | "secondary" | "stop"
ui.code({ label, value, language })
ui.html({ value })
ui.clear_button({ … })                        // alias → button
ui.submit_button({ … })                       // alias → button

Layout & Chrome

ui.row(() => { /* children */ }, { equal_height, variant, gap })
ui.column(() => { /* children */ }, { scale, min_width, variant })
ui.group(() => { /* children */ }, { variant })
ui.accordion(() => { /* children */ }, { label, open })
ui.tabs(() => { /* children */ }, { selected })
ui.tab(() => { /* children */ }, { label, id })

Branding configuration (passed to instio options):

import { instio } from "@instio/core";

const app = instio({ branding: { name: "My App", logo: { key: "logo" } } }, (ui) => {
  ui.markdown({ value: "Welcome to my app!" });
});

Adding a new component

  1. Create src/components/my-component.js with a *Meta export.
  2. Register it on COMPONENT_MAP in that file.
  3. Import the file in src/bootstrapComponents.js.
  4. Implement the matching Svelte (or other) renderer component.

Events

Every ComponentHandle exposes:

handle.click(fn, [inputs], [outputs]);
handle.change(fn, [inputs], [outputs]);
handle.submit(fn, [inputs], [outputs]);

handle.stream(asyncGenerator).from(...inputs).to(...outputs);

Handler signatures

// Single output — return value is written to outputs[0]
function add(a, b) {
  return Number(a) + Number(b);
}

// Multiple outputs — return an array
function split(text) {
  return [text.toUpperCase(), text.length];
}

// No inputs — omit the inputs array
function reset() {
  return "0";
}
btn.click(reset, [], [display]);

// Streaming — async generator, each yield updates outputs
async function* generate(prompt) {
  for await (const token of streamFromAPI(prompt)) {
    yield token;
  }
}

Input / output wiring

  • Inputs — component handles (or arrays of handles) whose current values are passed to the handler.
  • Outputs — component handles whose stores receive the return value(s).
const prompt = ui.textbox({ placeholder: "Say hi" });
const output = ui.markdown();

ui.button({ label: "Run" })
  .click((text) => `**You typed:** ${text}`, [prompt], [output]);

State

The second argument to instio() is a lightweight reactive State container:

const app = instio((ui, state) => {
  state.set({ count: 0 });

  const counter = ui.number({ label: "Count", value: 0 });
  counter.bind(state);

  ui.button({ label: "Increment" }).click(() => {
    state.set({ count: state.get().count + 1 });
  });
});

| Method | Description | |--------|-------------| | state.get() | Snapshot of current state | | state.set(partial) | Merge partial update and notify subscribers | | state.subscribe(fn) | Subscribe to changes; returns unsubscribe |

For complex app logic (calculator memory, multi-step wizards), module-level closures in app.js are also a practical pattern — handlers are real functions, not serialised strings.


Examples

| File | Description | |------|-------------| | examples/basic.js | Two number inputs, add button, readonly result | | examples/chat.js | Streaming chat with async generator | | ../instio/templates/src/app.js | Calculator with row/column grid layout |

Point @instio/svelte at any of these via INSTIO_APP:

INSTIO_APP=packages/core/examples/chat.js npm run dev   # from packages/svelte

Advanced Exports

For renderer authors and tooling:

| Export | Description | |--------|-------------| | Builder | Builds and traverses the component node tree | | ComponentHandle | Fluent event API wrapper | | Event | Click / change / submit event descriptor | | StreamEvent | Async-generator streaming event descriptor | | Node | Base UI node | | Block | Layout block node | | Slot | Slot node | | State | Reactive state container | | createUI | Low-level DSL factory used by instio() | | *Meta | Renderer-agnostic prop schemas (ButtonMeta, TextboxMeta, …) |


Development

# From monorepo root
pnpm install
pnpm --filter @instio/core build    # ESM + CJS via tsdown
pnpm --filter @instio/core dev      # watch mode

License

MIT © Instio Contributors