Spaces:
Paused
Download AGENTS.md from oaklight/veilrender: direct link, hf CLI and curl.
- Browser
- Download file 6.41 kB
-
https://huggingface.co/spaces/oaklight/veilrender/resolve/main/AGENTS.md
- Command line
-
hf download hf://spaces/oaklight/veilrender/AGENTS.md
-
curl -L -o AGENTS.md https://huggingface.co/spaces/oaklight/veilrender/resolve/main/AGENTS.md
AGENTS.md β VeilRender
Context file for AI coding assistants. Symlinked as
CLAUDE.md.
What this project is
VeilRender is a headless browser rendering API β accepts a URL, renders it with a stealth Chromium browser (CloakBrowser + Patchright), returns HTML/Markdown/readability content. Designed as a fallback for fetch tools that fail on JavaScript-rendered pages.
Supports two deployment modes: single-instance (embedded browser) and gateway + worker pool (browser containers scale independently).
Only runtime dependency is patchright. Everything else is vendored from
zerodep β HTTP server, S3 client, HTML
parsing, readability extraction.
Architecture
Request flow
HTTP request β auth β route handler β browser_manager.get_page()
β
LocalWorker (embedded CloakBrowser)
RemoteWorker (CDP, Chromium)
PlaywrightWorker (Playwright protocol, Firefox/Camoufox)
Key components
| Component | File | Purpose |
|---|---|---|
| HTTP server | _vendor/httpserver |
Async HTTP framework (zerodep) |
| Browser pool | browser.py |
LocalWorker, RemoteWorker, PlaywrightWorker, BrowserManager |
| Config | config.py |
VEILRENDER_* env vars, worker protocol parsing |
| Routes | routes/*.py |
/render, /screenshot, /health, /metrics, /stats, / dashboard |
| Storage | storage.py |
L1 TTLCache + L2 S3 (vendored S3Client) |
| Filters | filters.py |
Outbound request blocklist (StevenBlack/hosts) |
| CDP proxy | cdp_proxy.py |
WebSocket proxy for direct CDP access |
| Stats | stats.py |
In-memory counters, p50/p95 latency |
Worker types
| Type | Connection | Browser | Stealth |
|---|---|---|---|
LocalWorker |
Local subprocess | CloakBrowser (auto-downloaded) | Browser-level + driver-level |
RemoteWorker |
chromium.connect_over_cdp() |
Any CDP-compatible Chromium | Driver-level (Patchright) |
PlaywrightWorker |
firefox.connect() |
Camoufox or Playwright-served Firefox | Browser-level (Camoufox) |
Repository layout
src/veilrender/
βββ app.py # HTTP server + CDP WebSocket multiplexing
βββ config.py # Settings from env vars (VEILRENDER_ prefix)
βββ auth.py # Token verification
βββ browser.py # Worker classes + BrowserManager pool coordinator
βββ cdp_proxy.py # CDP WebSocket proxy
βββ filters.py # Outbound request blocklist
βββ models.py # Request/response dataclasses
βββ stats.py # In-memory request counters and latency
βββ storage.py # L1 (TTLCache) + L2 (S3) render cache
βββ routes/
β βββ dashboard.py # GET / β stats dashboard with i18n (en/zh)
β βββ health.py # GET /health
β βββ metrics.py # GET /metrics β Prometheus exposition
β βββ render.py # POST /render
β βββ screenshot.py # POST /screenshot
βββ _vendor/ # zerodep modules β DO NOT EDIT manually
βββ httpserver.py # Async HTTP server
βββ cache.py # TTLCache
βββ s3.py # S3-compatible client
βββ readability.py # Article extraction
βββ soup.py # HTML parser
deploy/
βββ compose.yaml # Single-instance (prod)
βββ compose-dev.yaml # Dev instance (port 7861)
βββ compose-pool.yaml # Gateway + CloakBrowser workers
βββ compose-pool-mixed.yaml # Gateway + CloakBrowser + Camoufox
βββ Dockerfile.camoufox # Camoufox server image
scripts/
βββ download-cloakbrowser.py # Download CloakBrowser binary
Commands
make dev # Run dev server on :7860
make build # Docker build (full target, with CloakBrowser)
make build-gateway # Docker build (gateway target, no browser)
make run # Docker run
make lint # ruff check --fix && ruff format
make typecheck # ty check
make vendor # Re-vendor zerodep modules
Deployment
Dev deployment
make deploy-dev SSH_TARGET=oaklight.buttercup # single-instance
make deploy-dev SSH_TARGET=oaklight.buttercup POOL=1 # gateway + workers
Builds from the working tree (not committed state), tags as dev-test,
deploys to veilrender-dev stack (port 7861). Always verify no dirty files
in src/ before deploying.
Release
- Update
CHANGELOG.mdβ move[Unreleased]to[X.Y.Z] - Bump
__version__insrc/veilrender/__init__.py - Commit:
git commit -m "bump version to X.Y.Z" - Tag and push:
git tag vX.Y.Z && git push && git push origin vX.Y.Z - Release workflow auto-publishes to PyPI, Docker Hub, GHCR, and creates GitHub Release from changelog
Production
Prod runs on oaklight.buttercup at /dockervol/dockge/stacks/veilrender
(port 7860), exposed via NPS as veilrender.service.oaklight.top.
Update prod to a released version:
ssh oaklight.buttercup 'cd /dockervol/dockge/stacks/veilrender && \
docker compose pull && docker compose up -d'
Escalation
- Browser won't start β check
_find_browser_binary()cascade:CLOAKBROWSER_BINARYenv β~/.cloakbrowser/*/chromeβ auto-download - Remote worker won't connect β check
_resolve_to_ip()(Chromium rejects non-IP Host headers), verify CDP port is accessible - Camoufox worker won't connect β check Playwright version compatibility (client/server major.minor must match)
- Vendor module issue β never fix in-place; update upstream zerodep, re-vendor
- Test failure after 3 attempts β stop, report full output
- Never: delete files to fix errors, skip lint, modify
_vendor/directly
Files to never edit
src/veilrender/_vendor/**β vendored zerodep modules, update viamake vendororzerodep addfrom ~/projects/zerodepCLAUDE.mdβ symlink toAGENTS.md, editAGENTS.mdinstead
Definition of done
ruff check --fix && ruff formaton changed Python filesty checkpasses- Server starts and
/healthreturns 200 /renderreturns valid content for a test URL/metricsreturns valid Prometheus output