ArrowJS
ArrowJS is a tiny, blazing-fast, zero-dependency, type-safe UI framework for the agentic era, enabling isolation of agent-generated UI within WebAssembly sandboxes without requiring a build step.
ArrowJS is a UI framework described as tiny, blazing-fast, zero-dependency, and type-safe, requiring no build step. It positions itself as the first UI framework for the "agentic era," developed by Standard Agents, the team behind other notable projects like FormKit, Tempo, AutoAnimate, and Drag and Drop. The framework is built around standard JavaScript primitives, including Modules, functions, and template literals, making it essentially TypeScript. This design philosophy means that coding agents or developers familiar with TypeScript can readily understand and utilize it. A core aspect of ArrowJS is its ability to isolate component logic within WebAssembly (WASM) sandboxes, which allows for rendering full inline DOM directly within an application without relying on iframes or pre-defined UI components. This isolation mechanism is particularly suited for safely incorporating agent-generated user interfaces.
ArrowJS simplifies UI development by providing a minimal set of tools. It enables developers to build fast, maintainable applications and to deliver safe, flexible, on-demand UIs to users without the need for extensive upfront component planning. The entire framework is designed to be lightweight, running incredibly fast at less than 5kb over the wire, and eliminates the need for build steps, JSX compilation, React compilers, Vite plugins (though one exists for SSR), or Vue template compilers. Its fundamental operations are centered around just three core functions: reactive for state management, html for DOM rendering, and component for creating reusable UI elements. By adhering to JavaScript and TypeScript primitives, ArrowJS offers a highly flexible approach to UI construction, avoiding prescriptive "idiomatic" ways of use often found in larger frameworks.
Some of the key features are:
- Reactive Data: The
reactive()function transforms plain objects, arrays, or expressions into observable state that can be tracked and updated. It supports both direct data wrapping for mutable state and expression passing for computed values that automatically re-evaluate when their dependencies change. It also provides$onand$offmethods for manual subscriptions, thoughwatch()is generally preferred for side effects. - Templates: The
htmltagged template literal is used to create mountable DOM templates. These templates can render text, attributes, properties, lists, nested templates, and handle events. Expressions within templates are static by default, but can become reactive by wrapping them in callable functions, allowing for dynamic updates when underlying reactive data changes. Attributes can be toggled by returningfalsefrom their expressions. - SVG Templates: Similar to
html, thesvgtagged template literal is specifically designed for rendering SVG elements. It ensures that nested SVG content is correctly parsed within the SVG namespace, maintaining the same reactivity, list rendering, keying, hydration, and cleanup behaviors as standard HTML templates. - Components: ArrowJS components are plain functions wrapped with
component(). Each component mounts once per render slot, preserving its local state across parent re-renders. Components accept reactive objects as props, which should be read lazily inside expressions for live updates.onCleanup()can be used within components to register teardown logic for manual listeners, timers, or sockets when the component unmounts. Async components are also supported, resolving data before rendering and integrating seamlessly with SSR and hydration processes. - Watching Data: The
watch()function allows for defining derived side effects that automatically re-execute when their tracked reactive reads change. It supports both a single-effect form and a getter-plus-effect form, with dependencies being automatically discovered and dropped as needed. Watchers created within a component are automatically stopped upon component unmount. - Sandbox: The
@arrow-js/sandboxpackage enables running JavaScript/TypeScript/Arrow code within a WebAssembly virtual machine. This feature is crucial for isolating and safely executing AI-generated UI code, as the host page maintains ownership of the real DOM. Communication between the sandbox and the host occurs through serialized messages, and the sandbox renders via a stable<arrow-sandbox>custom element. It supportsmain.tsormain.jsentry files, optionalmain.css, and allows defining host bridge modules for sandbox code to import functions from the host. - Server-Side Rendering (SSR):
renderToString()is the main entry point for server-side rendering, converting a view into an HTML string and awaiting all async components to resolve. TheserializePayload()function then creates a<script type="application/json">tag to embed the hydration payload into the HTML document, facilitating client-side hydration. - Hydration: The
hydrate()function reconciles server-rendered HTML with the client-side view tree, re-establishing reactivity without replacing existing DOM nodes. It consumes theHydrationPayloadgenerated during SSR viareadPayload(). During hydration, if a subtree mismatches, ArrowJS can repair specific boundary regions instead of a full root replacement, enhancing resilience. - Routing Integration: The framework's Vite scaffold provides a simple
routeToPage(url)entry for consistent server and browser route resolution. It recommends utilizing the native Navigation API (window.navigation) for browser-only routing, with a fallback to the History API for broader browser support. - Utility Functions: Additional utilities include
onCleanup()for managing component lifecycle side effects,pick()(aliased asprops()) for narrowing reactive objects to specific keys while maintaining reactivity,nextTick()for flushing Arrow's internal microtask queue before executing a callback,render()for full-lifecycle client-side mounting,boundary()for marking hydration recovery regions,toTemplate()for normalizing diverse view values intoArrowTemplateinstances, andrenderDocument()for injecting rendered parts into an HTML shell in custom server setups.
To get started with ArrowJS, developers can scaffold a complete Vite 8 Arrow app, including SSR, hydration, and route-based metadata, using a single command: pnpm create arrow-js@latest arrow-app. For core runtime functionality without a build tool, ArrowJS can be installed via npm (npm install @arrow-js/core) or imported directly from a CDN using a module script. Development involves using the reactive() function to create observable state, the html tagged template literal for defining UI structures with dynamic expressions, and component() to encapsulate reusable logic and state. The ArrowJS Syntax VSCode extension provides syntax highlighting and autocomplete for html template literals. For advanced scenarios, such as safely incorporating AI-generated UI, the @arrow-js/sandbox package is utilized. Sandboxed code, typically in main.ts or main.js, exports an Arrow template or component, and can communicate with the host via output() calls or by importing host bridge modules. Server-side rendering involves calling renderToString() to generate HTML and a hydration payload, which is then passed to the client for hydrate() to reconcile the DOM.
Some common use cases include:
- Agent-Generated User Interfaces: Securely render dynamic and on-demand UIs created by AI agents or language models, isolating their logic within WebAssembly sandboxes to prevent untrusted code from directly interacting with the host DOM.
- Building Fast, Maintainable Web Applications: Develop lightweight and performant single-page applications or complex interactive frontends with a minimal, zero-dependency framework that streamlines state management and DOM updates without a build step.
- Creating Reactive Dashboards and Data Displays: Implement dynamic interfaces like data tables, live feeds, or visualizers where data changes are immediately reflected in the UI, leveraging reactive data and computed values for efficient updates.
- Delivering SEO-Friendly and Performant Websites: Utilize server-side rendering (SSR) to generate initial HTML for better search engine optimization and faster perceived load times, seamlessly hydrating the client-side application for full interactivity.
- Developing Reusable UI Component Libraries: Craft modular and stateful UI components using
component()for encapsulation, local state management, and props-based communication, ensuring stability and consistency across the application. - Interactive Tools and Widgets: Build small, self-contained interactive tools such as password generators, timers, or accordion menus where local component state and reactive expressions provide a fluid user experience.
- Complex Form Handling: Integrate with powerful form libraries or create custom input logic, leveraging reactive data to manage form state, validations, and dynamic UI elements efficiently.
- Dynamic List Rendering and Reconciliation: Manage lists of items, such as todo lists or photo galleries, with efficient DOM updates, element reordering, and state preservation across changes using keyed list rendering.
Comments
0Markdown is supported.