Changelog#
All notable changes to @revu-ai/server are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.3.0] - 2026-09-22#
Changed#
- Pre-filter. Browser user agents that contradict themselves in a way no shipped browser does are now reported: the legacy
Edge/token beside Chrome 79 or later, an iOS hardware model (such asiPhone13,2) in the platform slot, and a SafariVersion/newer than the iOS carrying it. REVU counts these as bots, so they were missed before.
[0.2.0] - 2026-09-16#
Added#
withRevuRoutes(reporter, routes)in@revu-ai/server/bunreports the requestsBun.serveanswers from itsroutestable, which never reachfetch. Handler functions and each method of a per-method route are wrapped. StaticResponseandBun.fileroutes are served through a handler that returns a copy, so they are reported, but Bun no longer answers them with304 Not Modified. HTML imports andfalseroutes pass through untouched. Keep wrappingfetchwithwithRevufor the paths no route matches.shouldReportoption: your own synchronous last check,(request) => boolean, run only for hits that pass every built-in filter andignorePaths.falsedrops the hit, and so does a check that throws. Use it for rules the path cannot express, such as skipping requests that bypassed your CDN.
[0.1.0] - 2026-09-15#
First release. Server-side crawler capture: the crawler requests that reach your own web server, including crawlers that never run JavaScript, are reported to REVU.
Added#
createRevuServer({ serverKey, ... })returns a reporter withtrack(),flush()andshutdown(). Every method is wrapped so it can never throw into the host server. A missing or public (revu_pk_) key yields a disabled reporter that does nothing.- Pre-filter. Only page-like GET and HEAD requests are considered (HTML documents plus
robots.txt,llms.txt,llms-full.txtand sitemap files). Known asset extensions,/api,/graphql,/_next/, health endpoints (/health,/healthz,/livez,/readyz,/ping) and non-HTML responses are skipped, andignorePathsadds your own. Health-check probes (kube-probe,ELB-HealthChecker,GoogleHC,Consul Health Check,Envoy/HC) are never reported. Redirects count whatever their content type. A user-agent check keeps ordinary browser traffic, and requests without a user agent, from ever being sent. - Privacy at the source. Each
$crawlevent carries host, path, method, status, user agent, client IP, referer host and timestamp. The query string is stripped unless a parameter is listed inqueryAllowlist, and path parameters (such as ajsessionid=...session id) are always stripped. Bodies, cookies and other headers are never read. - Trusted client IP.
trustProxy(hop count ortrue, also as a string from the environment) andipHeadercontrol whenX-Forwarded-Foror a single-value edge header is used. Otherwise the socket address is. WithipHeaderset, a request without that header falls back to the socket address. WithtrustProxyon, the reported host comes fromX-Forwarded-Hostwhen present, so a site behind a reverse proxy reports its real host. Withdebugon,trustProxy: truewithoutipHeaderlogs a one-time warning, since clients control the leftmostX-Forwarded-Forentry. - Bounded delivery. A capped in-memory queue (oldest dropped when full), a flush every 5 s or at 20 hits, sends spaced at least 1 s apart (
minSendIntervalMs) so a burst goes out as one batch, including on edge runtimes that flush after every hit, one request in flight, a 3 s timeout, one retry then drop, exponential backoff,Retry-Afteron 429, smaller batches after 413, and no sending after 401 until restart. A sharedbeforeExithook makes one final attempt on natural exit, bounded by the timeout.maxBatchSizeis capped at 500, the API limit, and each batch carriessent_atso REVU can correct clock skew. Withdebugon, each send logs REVU's per-hit counts (accepted, duplicates and rejections by reason). - Adapters.
@revu-ai/server/node(node:http, Express, Connect),/fastify,/fetch(any fetch-style handler),/bun,/deno,/cloudflare(options built fromenv, flush throughctx.waitUntil) and/next(middleware, flush throughevent.waitUntil). - Types.
.d.tsdeclarations generated from JSDoc for every entry point. - Zero runtime dependencies. Runs on Node 20+, Bun, Deno, Cloudflare Workers and Next.js middleware.