New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@vexralabs/zerodom

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vexralabs/zerodom

DOM-to-Interaction-Graph middleware for AI web agents (TypeScript port)

latest
Source
npmnpm
Version
0.0.7
Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

@vexralabs/zerodom

The visual action layer for AI web agents — TypeScript edition.

See the page. Know exactly what to click.

npm version License

TypeScript port of ZeroDOM's core engine — same interaction graph, same selector guarantees, for the Node/TS agent stack (LangChain.js, the Vercel AI SDK, Playwright for Node).

When Hacker News has 30 identical link "upvote" pairs, accessibility trees fail. ZeroDOM assigns 1:1 deterministic handles, resolving [45] to the exact DOM element while keeping CSS selectors entirely out of the context window.

Install

npm install @vexralabs/zerodom

Quickstart

import { ZeroDOM } from "@vexralabs/zerodom";

const graph = await ZeroDOM.fromPage(page);   // any Playwright Page
console.log(graph.toCompactText());           // what you send the model
const selectors = graph.selectorMap();        // { node_01: "#email-input", ... } — stays your side
import { parseHtml } from "@vexralabs/zerodom";

const graph = parseHtml(html, url);           // parse HTML you already have, no browser needed

Real output, 11,882 tokens of Hacker News → 2,326:

PAGE: Hacker News | https://news.ycombinator.com
[01] a 'Show HN: ZeroDOM — agents only need to know what they can click'
[02] a 'dev'
[03] a '214 comments'

Core features

  • Deterministic parse, no LLM in the loop. lxml-equivalent engine on linkedom, identical output every run. Sub-50ms on most pages.
  • Selectors never enter the context window. The model sees [03]; the CSS path stays in selectorMap() on your side.
  • Shadow DOM handled. Open shadow roots are parsed and light-DOM selectors are scoped with :light(…). Pages with no shadow root pay nothing.
  • Structural action diffs. + appeared, - gone, ~ value changed — agents stop re-reading entire pages.
  • iframe support. Pass { frames: true } to read same- and cross-origin frames.

API

import { ZeroDOM, parseHtml } from "@vexralabs/zerodom";

// From a Playwright page (any object with content()/url()):
const graph = await ZeroDOM.fromPage(page);

// From raw HTML:
const graph = parseHtml(html, url);

// What to send the model:
graph.toCompactText();                    // "[01] a 'Sign In'\n[02] input 'Email'..."
graph.toCompactText({ selectors: true }); // includes CSS selectors
graph.toCompactText({ hrefs: true });     // includes link destinations

// What stays on your side:
graph.selectorMap();  // { node_01: "#email-input", ... }

// Metadata:
graph.metadata;  // { page_title, url, total_interactive_nodes, parsing_latency_ms, warning? }

Why linkedom, not jsdom

linkedom gives a real querySelector/getElementById DOM — needed so every generated selector can be self-verified, the same guarantee the Python version makes against a real browser — at a fraction of jsdom's footprint. One caveat this port works around: unlike jsdom or a real browser, linkedom's parser doesn't normalize a bare HTML fragment into a full <html><body> document, so ZeroDOMParser wraps non-document input itself before handing it to linkedom (page.content() output is unaffected — it's always a full document already).

Development

npm install
npm run build   # tsc -> dist/
npm test        # node's built-in test runner, against the built dist

License

Apache 2.0 — see LICENSE.

Keywords

dom

FAQs

Package last updated on 17 Sep 2026

Related posts