
Security News
vlt 1.5.0 Adds Agent Skills Management
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.
@opendatalabs/darshana
Advanced tools
Crawl any web app and generate a labeled PDF, HTML viewer, or image set for design review.
Crawl any web app and generate a labeled PDF, HTML viewer, or image set for design review.
Darśana — Sanskrit for "the act of seeing clearly."
npx @opendatalabs/darshana --url https://vana.org --public --max-pages 10
Output lands in ./darshana-output/ — a PDF and a self-contained HTML viewer with sidebar nav, filters, and keyboard navigation.
For a private app, darshana opens a browser so you can log in, then saves the session:
npx @opendatalabs/darshana --url https://app.vana.org
# A browser opens → log in → press Enter → capture begins
npm install -g @opendatalabs/darshana
Chromium is installed automatically. Or skip the install entirely and use npx @opendatalabs/darshana.
Linux only: if Chromium fails to launch, you may be missing system libraries. Fix with:
sudo npx playwright install chromium --with-deps
darshana --url <url> [options] # zero-config
darshana --config <path> [options] # file-based (CLI args override config)
--url <url> Base URL to crawl
--config <path> Path to a JSON config file
--title <string> Review title (default: hostname)
--start <path> Starting path (default: /)
--public Skip auth — use for public sites
--auth-storage <path> Where to save/load the session (default: ./darshana-output/auth.json)
--auth-script <path> Headless login script (see Auth below)
--themes <list> Comma-separated: system,dark,light (default: system)
--viewports <list> Comma-separated: desktop,mobile (default: desktop)
--max-depth <n> BFS depth limit (default: 5)
--max-pages <n> Page cap (default: 100)
--delay <ms> Wait after page load before capture (default: 400)
--outputs <list> Comma-separated: pdf,html,images (default: pdf,html)
--output-dir <path> Output directory (default: ./darshana-output)
--include <regex> Crawl only paths matching this pattern (repeatable)
--exclude <regex> Skip paths matching this pattern (repeatable)
--dry-run Discover URLs without capturing
--route <path> Capture a single route only
--auth-only Save auth session and exit
For complex projects, a JSON config gives you per-route sampling rules and capture overrides. CLI args always override config file values.
{
"title": "My App",
"url": "https://myapp.example.com",
"start": "/dashboard",
"public": false,
"authStorage": "./auth.json",
"authScript": "./auth.mjs",
"crawl": {
"include": ["^/dashboard"],
"exclude": ["logout", "delete"],
"maxDepth": 3,
"maxPages": 50,
"routes": [
{ "pattern": "/dashboard/records/:id", "sample": 1, "follow": false },
{ "pattern": "/dashboard/runs/:id", "sample": 2, "follow": false },
{ "pattern": "/dashboard/**", "follow": true }
]
},
"capture": {
"themes": ["dark", "light"],
"viewports": ["desktop", "mobile"],
"delay": 400,
"overrides": [
{ "route": "/dashboard/records/", "delay": 1000 }
]
},
"outputs": ["pdf", "html"],
"outputDir": "./output"
}
Without routes, darshana visits every discovered URL. For apps with millions of records or runs, use routes to sample:
| Field | Type | Default | Description |
|---|---|---|---|
pattern | string | required | Express-style path using :param and /** |
sample | number | unlimited | Max pages to capture matching this pattern |
follow | boolean | true | Whether to BFS-follow links on matching pages |
First match wins.
Top-level
| Field | Type | Default | Description |
|---|---|---|---|
title | string | hostname | Cover page and HTML header title |
url | string | required | Base URL |
start | string | / | Path to start crawling from |
public | boolean | false | Skip auth |
authStorage | string | ./auth.json | Saved session path |
authScript | string | — | Headless login script |
outputs | string[] | ["pdf","html"] | Any of "pdf", "html", "images" |
outputDir | string | ./darshana-output | Output directory |
crawl
| Field | Type | Default | Description |
|---|---|---|---|
include | string[] | [] | Regex patterns — pathname must match all |
exclude | string[] | [] | Regex patterns — pathname must not match any |
maxDepth | number | 5 | Max BFS depth |
maxPages | number | 100 | Hard page cap |
extraRoutes | string[] | [] | Extra paths to capture (not crawled for links) |
routes | Route[] | [] | Per-pattern sampling rules |
capture
| Field | Type | Default | Description |
|---|---|---|---|
themes | string[] | ["system"] | "system" (no injection), "dark", "light" |
viewports | string[] | ["desktop"] | "desktop" (1440×900) or "mobile" (390×844) |
fullPage | boolean | true | Capture full scrollable height |
delay | number | 400 | ms to wait before capture |
waitFor | string | — | CSS selector (prefix $) or JS expression to await |
overrides | Override[] | [] | Per-route overrides for any capture field |
contextOptions | object | {} | Passed to browser.newContext() |
launchOptions | object | {} | Passed to chromium.launch() |
playwrightOptions | object | {} | Passed to page.screenshot() |
routeOptions | object | — | { blockPatterns: string[] } — abort matching requests |
Headed handover (default): darshana opens a Chromium window, you log in, press Enter. The session is saved to authStorage and reused for 12 hours.
Headless auth script: export a default function that receives a Browser and returns the path to a saved storageState:
// auth.mjs
export default async function login(browser) {
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(process.env.APP_URL + '/login');
await page.fill('#password', process.env.APP_PASSWORD);
await page.click('button[type="submit"]');
await page.waitForURL(/\/dashboard/);
await context.storageState({ path: './auth.json' });
await context.close();
return './auth.json';
}
See examples/auth-example.mjs for a full example.
pdf — one page per capture, labeled header, cover pagehtml — self-contained file with sidebar nav, theme/viewport filters, keyboard navigation (↑↓), viewport-correct image sizingimages — <outputDir>/images/<viewport>/NNN-slug-theme.pngMIT
FAQs
Crawl any web app and generate a labeled PDF, HTML viewer, or image set for design review.
The npm package @opendatalabs/darshana receives a total of 0 weekly downloads. As such, @opendatalabs/darshana popularity was classified as not popular.
We found that @opendatalabs/darshana demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.

Security News
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.