A client-side web foundation for single-page-apps
/___\ ___ _
)O.o( |\/| o | |_ BE small
\_^_/ | | | | |_ be STRONG
" "
Brain space is limited, time is limited, ideas are abundant, so enter: Mite JS
We have all been there...
Its midnight. You need sleep. With morning comes work and it has demands, but you have an idea that you cannot shake. You need to just get it out of your head and into some code. You could grab one of the heavy-weight champions, but you don't have time for all the boilerplate fluff. You could also reach for AI, but that is prompt-after-prompt until the sun comes up -- no time for that.
Build your idea NOW, no distractions, minimal Mite work!
- Minimalist: ~2.2KB minified.
- Hyperscript Syntax: Fast, readable component building.
- Reactive State: Built-in global signal with a simple
.update()API. - Smart Patching VDOM: Key-aware diffing and robust Fragment support.
- Parametric Hash Router: Support for dynamic routes (e.g.,
/user/:id). - Build Variation: From min-to-full featured your choice.
Add More...
Mite also includes a collection of minimal language agnostic helpers, you can include in your builds or use with any other framework or just plain Javascript
- HTTP Client
- DOM Utility
- Local Storage
- Session Storage
- Cookie Storage
See /docs from more information.
Just import Mite JS in your project
import { h, mount } from './mite.min.js';You REALLY only need TWO functions
That seriously reduces congnitive load!
Depending on your needs, there are a few variations, see below
| Build | Size* | Features |
|---|---|---|
| Minimal | ~2.2KB | minimal h, mount, signal |
| HTML | htm syntax html, mount, signal |
|
| Core | ~3KB | for SPA h, route, signal |
| Full | ~4KB | adds http, dom($), local, session, and cookie utilities |
* Minified Size,
gzipis event SMALLER!
The simplest way to see reactivity in action using mount.
import { h, mount } from '../dist/mite.min.js';
const Counter = ({state, update}) => {
return h('div', { class: 'container' }, [
h('h2', {}, `Count: ${state.count}`),
h('div', { class: 'grid' }, [
h('button', { onclick: () => update({ count: state.count + 1 }) }, '+1'),
h('button', {
class: 'secondary',
onclick: () => update({ count: state.count - 1 })
}, '-1')
])
]);
}
mount('#app', Counter, { count: 0 });This example demonstrates list rendering with key for performance and how to handle form inputs.
import { h, mount } from '../dist/mite.min.js';
const TodoApp = ({state, update}) => {
const addTodo = (e) => {
e.preventDefault();
const input = e.target.querySelector('input');
if (!input.value) return;
update({
todos: [...state.todos, { id: Date.now(), text: input.value }]
});
input.value = '';
};
return h('article', [
h('header', [h('h3', {}, 'My Tasks')]),
h('form', { onsubmit: addTodo }, [
h('fieldset', { class: 'grid' }, [
h('input', { placeholder: 'What needs doing?' }),
h('button', { type: 'submit' }, 'Add')
])
]),
h('ul', [
state.todos.map(todo => h('li', { key: todo.id }, todo.text))
])
]);
};
mount('#app', TodoApp, { todos: [] });Rendering raw html can be achived with the property key of html, and the value of the html you would like to render. Treat as UNSAFE, only VERY basic sanitation provided
h("p", {html: "I'm your <strong>Huckleberry</strong>"})Mite shines when building multi-page interfaces. The route passes params (like :id) directly to your views
import { h, route } from '../dist/mite.core.min.js';
// Master View
const Home = ({state}) => h('div', [
h('h1', 'Project Dashboard'),
h('ul', [
state.projects.map(p => h('li', [
h('a', { href: `#/project/${p.id}` }, `View ${p.name}`)
]))
])
]);
// Detail View
const Detail = ({state, update, params}) => {
const project = state.projects.find(p => p.id == params.id);
return h('article', [
h('header', {}, h('h2', {}, project?.name || 'Not Found')),
h('p', {}, 'Detailed project metrics would go here.'),
h('footer', [h('a', { href: '#/' }, '← Back Home')])
]);
};
const routes = {
'/': Home,
'/project/:id': Detail,
'404': () => h('h1', {}, '404: Lost in space')
};
const state = {
projects: [
{ id: 1, name: 'Alpha Station' },
{ id: 2, name: 'Deep Space 9' }
]
};
route('#app', null, state, {routes});It provides the smallest foot-print, requires no build step, still quite readable.
| Function | Description |
|---|---|
h(tag, props, ...children) |
Hyperscript style UI component. Returns DOM. |
mount(selector, view, state = {}, opts = {}) |
Mounts component to DOM. Returns a signal. |
signal(initial, log = false) |
Creates reactive signal store |
or XHTM Alternative via Template Literal syntax.
A special build of mite is generated, test.build.js that exports everything and is placed in the tests/ directory. This file is ignored by default.
bun run testNOTE:
bun testwill fail.test.build.jsmust exist first viabun run testor usebun run test:buildfirst.
bun run buildPlease open an issue for support.
Anyone is welcome to contribute, however, if you decide to get involved, please take a moment to review the guidelines, they're minimalistic;)
- add more
tests/ - maybe add
test.itas a client-side testing utility intosrc/ - improve github pages
- add more examples
Currently dogfooding Mite.js against various apps, small and big and adjusting to what feels right for all scenarios.
Official v1.0.0 release coming soon!