by lukejacksonn

lukejacksonn / ijk

Transforms arrays into virtual dom trees; a terse alternative to JSX and h

445 Stars 13 Forks Last release: Not found MIT License 73 Commits 25 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:


Transforms arrays into virtual DOM trees

Build Status codecov


a bit repetitive? Not a huge fan of JSX? Love LISP? Code as data and data as code?

This is a tiny recursive factory function that allows you to write terse, declarative representations of virtual DOM trees. It does not try mimic HTML or JSON syntax but instead a series of nested arrays to represent user interfaces.

const tree = h('x', 'y', 'z')
  ['main', [
    ['h1', 'Hello World'],
    ['input', { type: 'range' }],
    ['button', { onclick: console.log }, 'Log Event'],

The above call to

returns a virtual DOM tree with named attributes that respect the provided schema. Expected output here, would be of the shape
{ x: 'main', y: {}, z: [...] }
. A tree like this can be passed as a node to patch, diff and render algorithms exposed by libraries like Hyperapp, Ultradom or Preact.


  • Hyperapp / Ultradom / Preact:


A call to

returns a build function that expects a node of type
  • Index
    contains a
    used as the elements tag name (required)
  • Index
    contains an
    containing element attributes (optional)
  • Index
    contains an
    of content or children (optional)

Children are flattened and falsey children are excluded. Numbers passed as children get converted to strings.


npm i ijk


Here is a demo with Hyperapp and Preact.

import { h } from 'ijk'

const tree = h('nodeName', 'attributes', 'children')( ['main', [ ['h1', 'Hello World'], ['input', { type: 'range' }], ['button', { onclick: console.log }, 'Log Event'], ['ul', [ ['li', 1], ['li', 2], ['li', 3] ]], false && ['span', 'Hidden'] ]] )


ijk is essentially

but with optional props and you only have to call
once; not every time you want to represent an element in the DOM. This generally means less repetition and one less import in your view files.
const h =
  h('main', {}, [
    h('h1', {}, 'Hello World'),
    h('input', { type: 'range' }),
    h('button', { onclick: console.log }, 'Log Event'),
    h('ul', {}, [
      h('li', {}, 1),
      h('li', {}, 2),
      h('li', {}, 3),
    false && h('span', {}, 'Hidden')

The main advantages over using JSX is less repetition of tag names and no build step is required.

const jsx =

Hello World

Log Event
  • 1
  • 2
  • 3
{false && 'Hidden'}


Here is an example that takes advantage of most features and demonstrates components.

import { h } from 'ijk'

const Item = data => ['li', data] const Article = ({ title, story, related }) => [ 'article', [ ['h2', title], ['hr'], ['p', story], related.map(Item), ] ]

const Main = ['main', [ ['h1', 'Hello World'], ['input', { type: 'range' }], ['ul', [ ['li', 1], ['li', 2], ['li', 3], ]], ['button', { onclick: console.log }, 'Log Event'], false && ['span', 'Hidden'], Article({ title: 'Some News', story: 'lorem ipsum dolor sit amet', related: [4,5], }) ]]

const tree = h('nodeName', 'attributes', 'children')(Main)

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.