Browser Compat is a small toolkit for generating browser compatibility
manifests, checking them against a project's browserslist targets, and using
the result at runtime to adjust the user experience.
It is designed for applications that want browser compatibility decisions to be
driven by the consuming project, not by hard-coded package defaults. Browser
targets come from your own browserslist configuration or from an explicit CLI
override.
- Reads an explicit project
browserslistconfiguration. - Generates a compatibility manifest for build and runtime use.
- Scans source usage into required, optional, CSS, and performance capability reports.
- Checks whether a generated manifest is still current after browser target changes.
- Provides a browser runtime that validates the manifest, detects declared
features, and injects
compat-*classes. - Provides React bindings for application-level compatibility state and banners.
- Generates a minimal early boot fallback script for unsupported browsers.
- Reports high-cost CSS and can generate scoped low-power CSS overrides.
Most applications do not need to install every package directly.
| Package | Use it when |
|---|---|
@browser-compat/cli |
You need the browser-compat CLI during development or CI. |
@browser-compat/react |
You use React or Next.js and want CompatProvider, useCompat, or CompatBanner. |
@browser-compat/boot |
You want an early unsupported-browser fallback before the app bundle runs. |
@browser-compat/runtime |
You want to use the runtime directly without React. |
@browser-compat/core |
You need shared manifest types, validation, or status decisions. |
@browser-compat/capabilities |
You need programmatic capability mapping. |
@browser-compat/postcss |
You need programmatic CSS risk scanning or low-power CSS generation. |
For a typical React or Next.js app, install:
npm install @browser-compat/react @browser-compat/boot
npm install -D @browser-compat/cliAdd an explicit browserslist configuration to the consuming project. For
example, in package.json:
{
"browserslist": [
"Chrome >= 109",
"Edge >= 109",
"Firefox >= 115",
"Safari >= 16"
]
}--strict-browserslist makes the CLI fail when no explicit project
configuration is found.
Generate a manifest, a capability report, a CSS report, and scoped low-power CSS:
npx @browser-compat/cli generate \
--project . \
--out generated/browser-compat.manifest.json \
--capabilities generated/browser-compat.capabilities.json \
--css-report generated/browser-compat.css-report.json \
--css-out src/styles/browser-compat.generated.css \
--css-mode generate \
--strict-browserslistAfter installing @browser-compat/cli, the same command can be run as:
browser-compat generate \
--project . \
--out generated/browser-compat.manifest.json \
--capabilities generated/browser-compat.capabilities.json \
--css-report generated/browser-compat.css-report.json \
--css-out src/styles/browser-compat.generated.css \
--css-mode generate \
--strict-browserslistAdd scripts to your app:
{
"scripts": {
"browser-compat:generate": "browser-compat generate --project . --out generated/browser-compat.manifest.json --capabilities generated/browser-compat.capabilities.json --css-report generated/browser-compat.css-report.json --css-out src/styles/browser-compat.generated.css --css-mode generate --strict-browserslist",
"browser-compat:check": "browser-compat check --project . --manifest generated/browser-compat.manifest.json --strict-browserslist"
}
}Run browser-compat:generate during setup or before builds. Run
browser-compat:check in CI to catch stale manifests after browserslist
changes.
@browser-compat/cli installs the browser-compat command.
browser-compat prepare --project <dir> --out <file> [--strict-browserslist] [--targets "..."] [--with-capabilities]
browser-compat check --project <dir> --manifest <file> [--strict-browserslist]
browser-compat report --project <dir> [--out <file>] [--css-report <file>] [--strict-browserslist] [--format json]
browser-compat generate --project <dir> --out <manifest-file> [--capabilities <file>] [--css-report <file>] [--css-out <file>] [--css-mode report|generate] [--strict-browserslist]Common commands:
browser-compat report \
--project . \
--out generated/browser-compat.capabilities.json \
--css-report generated/browser-compat.css-report.json \
--strict-browserslist \
--format jsonbrowser-compat check \
--project . \
--manifest generated/browser-compat.manifest.json \
--strict-browserslist@browser-compat/react exports:
CompatProvideruseCompatCompatBanner
Example:
import { CompatBanner, CompatProvider } from "@browser-compat/react";
import manifest from "../generated/browser-compat.manifest.json";
import "./styles/browser-compat.generated.css";
export function App({ children }: { children: React.ReactNode }) {
return (
<CompatProvider manifest={manifest}>
<CompatBanner hiddenStatuses={["ok", "degraded"]} />
{children}
</CompatProvider>
);
}You can also load the manifest by URL:
<CompatProvider manifestUrl="/browser-compat.manifest.json">
<CompatBanner />
{children}
</CompatProvider>CompatBanner can be customized with localized messages or a custom render
function:
<CompatBanner
messages={{
unsupported: "This browser is missing required capabilities.",
lowPower: "Low power mode is enabled for this browser."
}}
/>Use @browser-compat/runtime directly when your application does not use
React:
import { initCompatRuntime } from "@browser-compat/runtime";
import manifest from "../generated/browser-compat.manifest.json";
const state = await initCompatRuntime({ manifest });
if (state.decision.status === "unsupported") {
// Render an unsupported-browser fallback.
}The runtime validates the manifest before evaluating features. It detects only
features declared by the manifest or passed explicitly through features.
@browser-compat/boot creates a small script that can run before the main app
bundle. It checks a minimal set of boot-critical browser APIs and inserts an
unsupported-browser banner if those APIs are missing.
import { createCompatBootScript } from "@browser-compat/boot";
const script = createCompatBootScript({
message: "Please upgrade your browser to continue."
});In an HTML document or framework layout, inject the returned script before the main application bundle.
@browser-compat/postcss can report expensive CSS declarations such as
animation, transition, filter, backdrop-filter, box-shadow, and text-shadow.
When generation is enabled, the CLI writes scoped overrides under
.compat-low-power <selector>.
The generator avoids broad global selectors such as .compat-low-power *, so
the generated CSS can be reviewed and imported like any other project CSS file.
A typical setup may generate:
| File | Purpose |
|---|---|
generated/browser-compat.manifest.json |
Runtime manifest based on current browser targets and detected capabilities. |
generated/browser-compat.capabilities.json |
Build-time capability report for auditing source usage against browser targets. |
generated/browser-compat.css-report.json |
CSS risk report for high-cost declarations. |
src/styles/browser-compat.generated.css |
Optional low-power CSS overrides scoped under .compat-low-power. |
Commit generated files only if that matches your application's build and deploy
workflow. In CI, run browser-compat check to make sure committed manifests
stay in sync with browserslist.
- Browser targets belong to the consuming project.
- The package does not ship business-specific browser versions, memory thresholds, or routes.
- Build-time scanning and runtime decisions are separate.
- Runtime detection checks declared features instead of guessing broad browser support from user-agent strings.
- Low-power CSS output is scoped and reviewable.
This repository is a npm workspace package.
npm install
npm run build
npm run typecheck
npm testRun the full prepublish verification:
npm run prepublish:check