Introduction
Safi Studio Scanner is a website audit engine for Node.js, written in TypeScript. You give it a URL. It crawls the site, runs 93 checks against every page it finds, scores the results, and returns one report.
It ships as a library, not a command line tool. There is no binary to install globally and no config file to maintain. You import a function, call it, and get an object back.
What it is for
- A scriptable audit you can run in CI and fail a build on.
- A report you can hand to a client, rendered as one self-contained HTML file.
- A JSON feed for a dashboard, a database, or your own reporting layer.
- A base to extend, because a rule is one small module and the registry is exported.
Design decisions
The core install has one dependency. Cheerio parses the HTML. Nothing else is required. A project that never renders a page never installs Chromium.
Rendered checks are optional and come two ways. Accessibility and Core Web Vitals need a real browser. You can supply one locally with Playwright, or skip the install entirely and use the Google PageSpeed Insights API. Both feed the same rules.
Scoring is deliberately harsh. The overall score starts at 100 and deducts for every rule that fails or warns, weighted by severity and scaled by how much of the site it affects. A handful of real errors visibly drops the headline, the way a strict commercial auditor scores. A category average would hide them.
Rules are data, not framework. Each rule is an object with an id, a category, a severity, and a run(context) function. Adding one means writing a file and adding one import.
The pipeline
Five stages, one focused module each.
- Crawl. Up to
maxPagessame-origin pages from the start URL,concurrencyat a time, no deeper thanmaxDepth.robots.txtandsitemap.xmlare fetched once for the site and shared with every rule. - Context. Each page becomes a
PageContext: final URL, status, headers, raw HTML, a parsed DOM, response time, redirect count, and every link and image already extracted. - Render, optional. With
browser: trueor apsiKey, each page also carries axe-core violations and real Core Web Vitals. - Run. Every selected rule runs against every page and returns findings. A rule that throws is caught and downgraded to a warning, so one bad rule cannot take down a run.
- Score and render. Findings are weighted by severity into a score per page, per category, and overall, then rendered as JSON, Markdown, or HTML.
What a finding looks like
Every check returns one or more findings. A finding is small and flat on purpose.
Where to go next
- Getting started to install and run your first audit.
- Configuration for every option.
- Rule catalog for all 93 checks.
- Roadmap for what is in progress and what comes next.