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 as iPhone13,2) in the platform slot, and a Safari Version/ 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/bun reports the requests Bun.serve answers from its routes table, which never reach fetch. Handler functions and each method of a per-method route are wrapped. Static Response and Bun.file routes are served through a handler that returns a copy, so they are reported, but Bun no longer answers them with 304 Not Modified. HTML imports and false routes pass through untouched. Keep wrapping fetch with withRevu for the paths no route matches.
  • shouldReport option: your own synchronous last check, (request) => boolean, run only for hits that pass every built-in filter and ignorePaths. false drops 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 with track(), flush() and shutdown(). 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.txt and sitemap files). Known asset extensions, /api, /graphql, /_next/, health endpoints (/health, /healthz, /livez, /readyz, /ping) and non-HTML responses are skipped, and ignorePaths adds 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 $crawl event carries host, path, method, status, user agent, client IP, referer host and timestamp. The query string is stripped unless a parameter is listed in queryAllowlist, and path parameters (such as a jsessionid=... session id) are always stripped. Bodies, cookies and other headers are never read.
  • Trusted client IP. trustProxy (hop count or true, also as a string from the environment) and ipHeader control when X-Forwarded-For or a single-value edge header is used. Otherwise the socket address is. With ipHeader set, a request without that header falls back to the socket address. With trustProxy on, the reported host comes from X-Forwarded-Host when present, so a site behind a reverse proxy reports its real host. With debug on, trustProxy: true without ipHeader logs a one-time warning, since clients control the leftmost X-Forwarded-For entry.
  • 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-After on 429, smaller batches after 413, and no sending after 401 until restart. A shared beforeExit hook makes one final attempt on natural exit, bounded by the timeout. maxBatchSize is capped at 500, the API limit, and each batch carries sent_at so REVU can correct clock skew. With debug on, 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 from env, flush through ctx.waitUntil) and /next (middleware, flush through event.waitUntil).
  • Types. .d.ts declarations generated from JSDoc for every entry point.
  • Zero runtime dependencies. Runs on Node 20+, Bun, Deno, Cloudflare Workers and Next.js middleware.