Skip to content

v0.3.0

Released 3 July 2026. Available on npm as orino-cli and @bynaree/orino.

Terminal window
npx orino-cli@latest audit

This release turns Orino from a single-page snapshot into a configurable, multi-page, CI-ready auditor. You can persist settings and silence false positives in a config file, audit a sample of pages across the whole site instead of just the homepage, catch routes that never made it into your sitemap (and sitemap URLs that no longer have a page), and wire the whole thing into a pipeline that fails only on real regressions.

Orino now reads settings from a config file, checked in this order: orino.config.json, then .orino/config.json, then an "orino" key in package.json. Every field is optional, and the resolution order is CLI flag > environment variable > config file > built-in default — so a flag always wins, and the file is there for the settings you do not want to retype on every run.

{
"url": "https://example.com",
"pages": 25,
"ignore": ["thin-content", "app/studio/**"],
"severity": { "thin-content": "info", "lcp-too-slow": "critical" },
"thresholds": { "lcp": 3000, "cls": 0.15, "inp": 300, "ttfb": 800 },
"failOn": "critical",
"baseline": "./orino-baseline.json"
}
  • ignore suppresses checks by ID ("thin-content") or by a glob matched against the finding location ("app/studio/**"). Suppressed checks report as skipped and are excluded from the score, exactly like any other skipped check.
  • severity promotes or demotes individual checks between critical, warning, and info. An info finding still appears in the output but never affects the score — the clean way to acknowledge an issue without letting it move the number.
  • thresholds overrides the Core Web Vitals warning thresholds (lcp/inp/ttfb in milliseconds, cls as a decimal).
  • psiStrategy switches PageSpeed Insights between mobile (default) and desktop.

Run orino init to drop a fully commented orino.config.json template into the current directory, with every option documented inline. A malformed config file fails loudly with a clear message and exit code 1, rather than being silently ignored.

See the Configuration reference for the full schema.

The new --pages <number> flag samples pages from your sitemap and runs the full URL check suite on each — metadata, on-page, structured data, canonical, and internal-link checks — instead of stopping at the homepage.

Terminal window
npx orino-cli audit --url https://example.com --pages 25
  • Pages linked from the homepage are prioritised, then the remaining sitemap URLs in order. Non-HTML entries (.xml, .pdf, images) are filtered out, and the homepage is always included.
  • Pages are fetched in parallel in batches of five, with a two-second pause between batches and a sixty-second overall cap, so a large sitemap never hammers your origin.
  • Pages that return a non-200 status are logged as an info finding and skipped — one dead URL never crashes the run.
  • The score is calculated across every page combined, and in --quiet mode a per-page summary table is printed at the end. Every finding now records which page it came from.

Two checks that previously had to skip on live audits are now real:

  • Duplicate titles and duplicate descriptions are flagged whenever any two sampled pages share the same value.
  • Article schema is verified on sampled blog posts (/blog/, /posts/, /articles/) rather than inferred from the homepage.

Default is --pages 0 (homepage only), so existing behaviour is unchanged unless you opt in.

Orino is the only audit tool that holds both your codebase route list and your live sitemap, so it can diff the two. Two new architecture checks run in full mode (codebase + URL) on Next.js projects:

  • Route missing from sitemap — a page exists in your codebase but not in sitemap.xml. If it should be indexed, add it. Dynamic routes ([slug]), API routes, and special pages are excluded.
  • Sitemap URL has no route — a URL sits in sitemap.xml with no matching route, usually a deleted page still lingering in the sitemap. CMS-style paths (/blog/, /posts/, /articles/) and content-ID URLs are excluded to avoid false positives on dynamically generated content.

Comparison strips domains and trailing slashes and is case-insensitive, and www and apex are treated as the same host. Outside full mode, both checks skip with an explanation.

  • --fail-on <level> sets the severity at which Orino fails the build: critical (default), warning, or any. Exit 0 means the threshold was met, 1 means issues at or above it were found, and 2 is reserved for configuration errors (invalid flags, a missing baseline, no framework and no URL).

  • --baseline <path> compares the run against a recorded baseline so CI fails only on new issues, not pre-existing ones. A finding counts as new when its check ID is not in the baseline. Generate one with the new orino baseline command:

    Terminal window
    npx orino-cli baseline --output ./orino-baseline.json
  • JSON output (--json) gains four fields for pipeline tooling: exitCode, newFindings, baselineCompared, and pagesAudited.

  • A ready-made GitHub Actions workflow ships at .github/workflows/orino.yml. It runs the audit, comments the score on pull requests, and fails the check when criticals are found.

  • Exit code semantics. Code 1 now means “issues found at or above the --fail-on level” (default critical, so the default behaviour is unchanged). Code 2 now also covers configuration errors — an invalid --fail-on value, a missing --baseline file, or a malformed config file — in addition to the existing “no framework and no URL” case.
  • Cross-page uniqueness is no longer skipped on live audits when you pass --pages; it becomes a real check across the sampled set. With a single page it still skips rather than guessing.
  • Core Web Vitals thresholds and PSI strategy are now configurable through the config file, where previously they were fixed at the mobile defaults.