@axewhyzed/blink-js
v2.3.0
Published
The Micro-Framework that thinks it's a Big Framework.
Readme
@axewhyzed/blink-js
BlinkJS is a small TypeScript UI runtime with fine-grained signals, a virtual-DOM renderer, component ownership, and optional application modules. It is designed to keep common application code readable: signals describe reactive state, components return DOM, and owned work is cleaned up with its component or root.
npm install @axewhyzed/blink-jsStart here:
Quick start
The root entry contains client-core APIs. Optional capabilities use explicit
subpaths such as @axewhyzed/blink-js/router,
@axewhyzed/blink-js/resource, @axewhyzed/blink-js/forms,
@axewhyzed/blink-js/portal, and @axewhyzed/blink-js/ssr.
import { el, mountApp, useSignal } from '@axewhyzed/blink-js';
function App() {
const count = useSignal(0);
return el('button', { onClick: () => count.value++ }, count);
}
mountApp('#app', App);Public entry points
The root entry contains client-core APIs:
- rendering:
el,mountApp,hydrateRoot,unmountApp, JSX helpers - reactivity:
useSignal,useComputed,createSignal,createEffect,createComputed,createRoot,batch,untrack, andnextTick - state:
createStore,useStore,produce, andunwrap - components:
Show,For,Switch,Match, andErrorBoundary - lifecycle:
onMount,onCleanup,useRef, and disposal helpers - context and DOM bindings
Production error reporting
Use setErrorReporter to forward framework-caught errors to your production
diagnostics service. It reports runtime, SSR, resource, router, and hydration
failures without changing BlinkJS error recovery or development console output.
import { setErrorReporter } from '@axewhyzed/blink-js';
setErrorReporter(({ error, source, component, path }) => {
telemetry.captureException(error, { tags: { source, component, path } });
});The callback is best-effort; if it throws, BlinkJS continues its normal error
handling. Calling setErrorReporter returns a function that restores the
previous reporter.
Optional features are explicit subpath imports:
| Feature | Import |
| ---------------- | --------------------------------- |
| Router | @axewhyzed/blink-js/router |
| Async resources | @axewhyzed/blink-js/resource |
| Forms | @axewhyzed/blink-js/forms |
| Portals | @axewhyzed/blink-js/portal |
| Server rendering | @axewhyzed/blink-js/ssr |
| Accessibility | @axewhyzed/blink-js/a11y |
| Testing | @axewhyzed/blink-js/testing |
| Transitions | @axewhyzed/blink-js/transitions |
| Devtools | @axewhyzed/blink-js/devtools |
The published package is validated as a consumer through native ESM, esbuild, Vite, Rollup, and Webpack. The repository's Playwright suite covers Chromium, Firefox, and WebKit behavior.
For example:
import { Router, Link, Outlet } from '@axewhyzed/blink-js/router';
import { createResource } from '@axewhyzed/blink-js/resource';
import { createForm } from '@axewhyzed/blink-js/forms';
import { renderToStringAsync } from '@axewhyzed/blink-js/ssr';Accessible UI helpers
@axewhyzed/blink-js/a11y provides small DOM controllers rather than a component
library. createDialog, createTabs, and createDisclosure connect existing
elements with the expected ARIA state, keyboard behavior, focus handling, and a
destroy cleanup method. They own the controlled dialog/panel hidden state;
keep application state in sync through their change callbacks.
import { createDialog, createTabs } from '@axewhyzed/blink-js/a11y';
const dialog = createDialog(() => document.querySelector('#settings')!, {
onOpenChange: (open) => (settingsOpen.value = open),
});
openButton.addEventListener('click', () => dialog.open());
const tabs = createTabs(tabList, [profileTab, billingTab], [profilePanel, billingPanel]);Dialogs are modal by default, close on Escape, trap focus while open, and restore
the previously focused element. Tabs use automatic activation by default; choose
activation: 'manual' when changing panels has a meaningful cost. For dialogs
rendered in an overlay container, closeOnOutsidePress closes only when that
container itself receives the pointer event.
Transitions and devtools
The transition element prop coordinates CSS enter and leave transitions.
When a conditional branch is removed, BlinkJS keeps its DOM range and component
ownership alive until leaveDuration completes, then runs cleanup and detaches
the range. Set leaveDuration: 0 for immediate removal, and use
onLeaveComplete for post-removal bookkeeping.
const fade = createTransition({
enter: 'fade-enter',
enterActive: 'fade-enter-active',
enterDuration: 180,
leave: 'fade-leave',
leaveActive: 'fade-leave-active',
leaveDuration: 140,
onLeaveComplete: () => console.log('removed'),
});installDevtools remains opt-in and bounded. Snapshots now include the configured
event capacity, how many old events were dropped, monotonically increasing event
sequences, and optional user-provided session metadata.
Server rendering concurrency
renderToStringAsync and renderToStream isolate hook and context state across
concurrent calls. A request that awaits inside a component cannot leak its
context to another request. This is safe on Node and runtimes exposing an
AsyncLocalStorage-compatible API. Do not call hook-using components directly
outside BlinkJS's SSR entry points.
The /full entry remains available for compatibility with the broad pre-2.1
surface. New applications should prefer explicit subpaths so unused features
remain tree-shakeable.
Learn more
The documentation site contains the beginner learning path, guides, runnable examples, production guidance, and a searchable reference for every public exported symbol. The API reference documents each symbol's import path, TypeScript signature, parameters, return value, runtime behavior, lifecycle, SSR notes, examples, common mistakes, and source file.
The repository contains complete runnable examples for a counter, todo app, router, portal, and SSR rendering. The migration guide explains the explicit optional-module imports introduced in the 2.x API.
Maintainers should use the repository's publishing checklist for versioning, validation, npm publication, and tagging.
MIT (c) BlinkJS Team
