ArrowJS: a reactive UI runtime built for coding agents
The first UI framework for the agentic era — tiny, performant, with WASM sandboxes for safe code execution.
At a glance
- What is it?
- ArrowJS is a small TypeScript UI runtime that renders reactive DOM updates from tagged template literals, with optional SSR, hydration and a QuickJS/WASM sandbox. It is aimed at teams that want a minimal API surface and expect coding agents to write the view layer.
- Who is it for?
- Adopt ArrowJS if you want a small reactive runtime with no build step for the core package and you are comfortable letting a coding agent write template-literal views. Do not adopt it if you need a large component ecosystem, an established router, or a framework whose every behaviour is documented in prose: the README does not document rollback, migration between minor versions, or what happens when the sandbox runtime is unavailable.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 92 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem ArrowJS targets: agents writing the view layer
Most UI frameworks assume a human author who learns a component model, a build pipeline and a set of conventions. ArrowJS assumes the author is a coding agent. The README states the framework is built around platform primitives that coding agents understand: JavaScript modules, template literals and the DOM. That is a real design constraint, not a slogan. Tagged template literals are ordinary JavaScript syntax, so an agent that can write a backtick string can produce a component without learning JSX transforms or a compiler-specific file format. The repository is a pnpm monorepo with the core runtime, framework, SSR, hydration, sandbox and Vite plugin split into separate packages, which means you can adopt the reactive core alone and ignore the rest. The audience is narrow on purpose: teams that generate or maintain front-end code with an agent and want the generated output to stay close to the platform.
How the reactive core and the async layers fit together
The layering is explicit in the README. @arrow-js/core stays DOM-first and framework-agnostic: reactive state, tagged-template rendering, components, pick() and props(), and nextTick(). @arrow-js/framework adds async render tracking and boundary(). @arrow-js/ssr provides renderToString() and serializePayload() for server output, and @arrow-js/hydrate provides hydrate() and readPayload() to adopt that HTML in the browser instead of replacing it. The constraint worth noting is that async components use the same component() API but require the async runtime from one of the framework, SSR or hydration packages to be imported before rendering. So the split is not free: if you use async components in core-only mode, nothing in the README suggests they will resolve. The sandbox package is the other distinct piece. @arrow-js/sandbox is described as a QuickJS/WASM-backed runtime that executes Arrow code off the host window realm while rendering into the real DOM. That is the mechanism behind the safe-code-execution claim in the repository description, and it is also the part with the least documentation in the README.
Installing ArrowJS and rendering a first counter
The README gives two paths. The scaffold command creates a complete Vite 8 Arrow app with SSR, hydration and the full framework stack. For a core-only start, install the single package with npm.
npm install @arrow-js/coreThe README states no build step is required for the core runtime, and it can be imported directly in the browser from esm.sh. The core example below is copied from the README: a component() call returns a function, reactive() holds state, and the click handler mutates state.count directly. The final line renders the component into document.body.
import { component, html, reactive } from '@arrow-js/core'
const Counter = component(() => {
const state = reactive({ count: 0 })
return html`<button @click="${() => state.count++}">
Clicked ${() => state.count} times
</button>`
})
html`${Counter()}`(document.body)After running this in a module script, you should see a button whose label updates on each click without a manual re-render call. For an existing project, the README also offers an agent skill that adds Arrow to a project you already have.
npx @arrow-js/skillFor the full SSR and hydration stack, the README lists the four packages to install together.
pnpm add @arrow-js/core @arrow-js/framework @arrow-js/ssr @arrow-js/hydrateWhere ArrowJS stops being the right tool
Two limitations are visible from the repository itself. First, the async story is split across packages and gated on import order: the README says async components require the async runtime from @arrow-js/framework, @arrow-js/ssr or @arrow-js/hydrate to be imported before rendering. A core-only application that starts using async components will not get them for free, and the README does not describe a diagnostic for that failure. Second, the sandbox is the headline capability in the repository description and the least specified in the README. It is described as QuickJS/WASM-backed and as running code off the host window realm, but the README does not state which globals are available inside the sandbox, how errors propagate back to the host, or what the performance cost of the WASM boundary is. The bench/ directory and the benchmark scripts in package.json suggest the maintainers measure performance, but the README does not publish results. If your requirement is a hardened execution boundary for untrusted third-party code, the README is not enough to judge it, and you should read the sandbox package source before relying on it.
How ArrowJS differs from Alpine.js and from Apache Arrow
The related searches mix two unrelated projects, and the distinction matters when you are choosing. Apache Arrow is a columnar data format with a JavaScript implementation; its related terms (arrow js ffi, Pyarrow js, Apache-arrow TypeScript) belong to that project, not this one. ArrowJS here is a UI runtime. The closer comparison in the search list is Alpine.js. Alpine augments existing HTML with directives in attributes, so the markup stays the source of truth and behaviour is declared inline. ArrowJS instead builds components in JavaScript and returns tagged template literals from component(), with reactive state held in a reactive() object and read inside interpolation slots. That means the view is produced by code rather than annotated in the document, which is easier for an agent to generate from scratch and harder to apply to a server-rendered page you do not control. ArrowJS also ships its own SSR and hydration packages, which Alpine does not, so the two only overlap on the client-side reactivity layer.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-07-01. The most recent release listed is v1.0.6 on 2026-04-01, with v1.0.5 the day before, and the previous line before that was 1.0.0-alpha.10 in February 2024. So the 1.0 line is roughly a year old at the time of writing, and the workspace package.json carries the same 1.0.6 version. The monorepo pins [email protected] through packageManager and requires Node >=20.19.0 || >=22.12.0, which is the first thing to check before upgrading an existing project. The verify script chains typecheck, test and build, so a local upgrade can be validated with the same commands the maintainers use. The licence is MIT, which permits commercial use and modification; the repository ships LICENSE.txt at the top level. This is not legal advice, and MIT does not cover the QuickJS/WASM components or any third-party dependency you pull in alongside the packages, so review the full dependency tree if licence compatibility matters to you.
Editorial conclusion
Adopt ArrowJS if you want a small reactive runtime with no build step for the core package and you are comfortable letting a coding agent write template-literal views. Do not adopt it if you need a large component ecosystem, an established router, or a framework whose every behaviour is documented in prose: the README does not document rollback, migration between minor versions, or what happens when the sandbox runtime is unavailable. Before committing, check that @arrow-js/core renders your existing markup, confirm the Node version against the engines field (>=20.19.0 || >=22.12.0), and read the sandbox package source to see what the QuickJS/WASM boundary actually isolates.
Frequently asked questions
What is ArrowJS in JavaScript?
ArrowJS is a TypeScript reactive UI runtime that renders DOM updates from tagged template literals, with components built through component() and state through reactive(). The repository splits it into @arrow-js/core plus optional framework, SSR, hydration and sandbox packages.
Is ArrowJS the same as Apache Arrow?
No. Apache Arrow is a columnar data format with its own JavaScript implementation, and search terms such as arrow js ffi and Pyarrow js refer to that project. ArrowJS here is a UI framework from standardagents/arrow-js.
Do I need a build step to use ArrowJS?
The README states no build step is required for the core runtime, and shows importing @arrow-js/core directly in the browser from esm.sh. The scaffolded Vite app and the SSR and hydration packages are a separate, larger setup.
What Node version does ArrowJS require?
The workspace package.json sets engines to node >=20.19.0 || >=22.12.0 and pins [email protected] through packageManager. That applies to working in the monorepo; the README does not state a separate Node requirement for consuming the published packages.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/standardagents-arrow-js)