npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rxova/repo-config

v0.9.0

Published

Repo maintenance for rxova monorepos: the verify gate, the changeset gate, pack smoke, llms.txt checks, and the shared build, test, lint and commit presets.

Readme

Every repository ends up with the same scripts: a pre-push gate, a changeset check, a tarball smoke test, a Node floor for CI. Copied, they drift. Here they are one bin, rxova-repo-config, read their settings from repoConfig in package.json, and sit beside one preset per tool, so a repository's differences are options rather than forks.

$ pnpm exec rxova-repo-config verify --only lint,format
verify: [1/2] lint
$ turbo run eslint:check
…
verify: [2/2] format
$ turbo run prettier:check
…
verify: all checks passed

What you get

| | | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 🚦 Verify gate | verify runs CI's checks in CI's order and stops at the first failure (or, with --keep-going, reports them all); pre-push is the whole .husky/pre-push hook. | | 📝 Changesets | check-changeset requires one when a published package changed; lint-changesets, add-changeset and version keep the changelog and lockfile right; version-pr opens the version pull request. | | 📦 Tarball checks | pack-smoke installs the packed tarball and loads it; check-exports runs publint and attw; post-publish-smoke loads what npm serves after a release. | | 📚 Docs checks | check-llms, check-tsdoc, check-banned and check-snippets hold llms.txt, TSDoc, docs and README snippets to the source. | | 🤖 CI helpers | check-scope, node-floor, check-majors, list-packages, dependabot-update-type and coverage-summary write what a workflow needs to GITHUB_OUTPUT or the job summary. | | 🧰 Presets | ESLint, Prettier, lint-staged, commitlint, changelog, tsdown, Vitest, Playwright, Knip and four tsconfigs. | | 🔌 Optional peers | Every tool is an optional peer dependency: install the ones you use. prettier-plugin-astro is the only dependency. |

Install

Add it once, to the repository root:

pnpm add -D -w @rxova/repo-config

In an rxova repository @rxova/repo-config is declared only in the root package.json, never in a workspace package: its presets and scripts run from the root, and a single copy keeps every package on the same rules.

Then install the tools for the presets and commands you use. They are optional peers, so nothing you do not use is pulled in:

| You use | Install | | --------------------------------------------- | ---------------------------------------------------------------------------- | | @rxova/repo-config/eslint | eslint, @eslint/js, typescript-eslint, globals, typescript | | … with react | eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-jsx-a11y | | … with astro | eslint-plugin-astro | | @rxova/repo-config/prettier | prettier (prettier-plugin-astro comes with this package) | | @rxova/repo-config/lint-staged | lint-staged, plus the ESLint and Prettier presets it runs | | @rxova/repo-config/commitlint | @commitlint/cli, @commitlint/config-conventional | | @rxova/repo-config/changelog | @changesets/cli, @changesets/changelog-github | | @rxova/repo-config/tsdown | tsdown | | @rxova/repo-config/vitest | vitest, @vitest/coverage-v8 (unless coverage: false) | | @rxova/repo-config/playwright | @playwright/test | | @rxova/repo-config/knip | knip | | check-exports | publint, @arethetypeswrong/cli | | check-llms, check-tsdoc, check-snippets | typescript |

Quick start

Point the root scripts and the git hook at the bin:

{
  "scripts": {
    "verify": "rxova-repo-config verify"
  }
}
# .husky/pre-push
pnpm exec rxova-repo-config pre-push

And each tool at its preset:

// eslint.config.js
import { rxova } from "@rxova/repo-config/eslint";

export default rxova({ tsconfigRootDir: import.meta.dirname, node: true, tests: true });
// lint-staged.config.js
export { default } from "@rxova/repo-config/lint-staged";
// commitlint.config.js
export { default } from "@rxova/repo-config/commitlint";
// .prettierrc
"@rxova/repo-config/prettier"
// tsconfig.json
{ "extends": "@rxova/repo-config/tsconfig.react.json", "include": ["src"] }
// .changeset/config.json
{ "changelog": ["@rxova/repo-config/changelog", { "repo": "rxova/<repo>" }] }
// packages/<name>/tsdown.config.ts, a React component package
import { defineConfig } from "tsdown";
import { reactBuildConfig } from "@rxova/repo-config/tsdown";

export default defineConfig(reactBuildConfig({ banner: { js: "'use client';" } }));
// packages/<name>/vitest.config.ts
import { baseVitestConfig } from "@rxova/repo-config/vitest";

export default baseVitestConfig({ root: import.meta.dirname });

With no repoConfig.verify.steps, verify runs the default gate, in CI's order:

| Step | Runs | | --------------------- | ------------------------------------- | | lint | pnpm lint | | format | pnpm format:check | | build | pnpm exec turbo run build | | typecheck | pnpm exec turbo run typecheck | | unit tests | pnpm exec turbo run test | | package exports | pnpm run check:exports | | pack smoke | pnpm run pack:smoke | | dependency versions | pnpm run sherif:check | | unused code | pnpm run knip:check | | dependency dedupe | pnpm exec turbo run //#dedupe:check | | audit | pnpm run audit:check |

So the root package.json needs those scripts, or its own verify.steps. --only "unit tests" picks steps by name.

Commands

rxova-repo-config --help lists them; --version prints the package version. Run each from the repository root, except pack-smoke and check-exports, which run from a package directory.

| Command | What it does | | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | rxova-repo-config verify [--only a,b] [--filter a,b] [--keep-going] | Runs the pre-push gate in order and stops at the first failure. The steps come from repoConfig.verify.steps, or the default list above. --only runs the named steps. --filter runs each split step in those packages only (--filter=a --filter=b appended to its command; other steps run unchanged); it fails when no selected step is split, or on a name with anything but letters, digits and _@./!-. --keep-going runs every step, still in order, then lists each failed step and its command and exits 1. verify --plan (alone) runs nothing and prints the gate as one line of GitHub Actions matrix JSON, {"include":[{"name","only","filter"}]}, one entry per job of a fan-out: a step on its own, a group together, a split step dealt into per-package jobs. | | rxova-repo-config pre-push [--only a,b] | The whole .husky/pre-push hook: a push that only deletes refs verifies nothing, any other push runs verify. | | rxova-repo-config check-changeset | Fails when a published package changed and no changeset was added, or when an added changeset would break the changelog. Reads BASE_SHA, HEAD_SHA, PR_LABELS, PR_TITLE; with PR_NUMBER set it reads the pull request's current labels through gh instead of PR_LABELS, falling back to PR_LABELS when that fails. | | rxova-repo-config lint-changesets | Fails a waiting changeset with a summary line @changesets/changelog-github reads as metadata (commit:, pr:, author:), and, with singlePackage, one naming two packages. | | rxova-repo-config add-changeset <pkg> <bump> <…> | Writes a one-package changeset without the prompt. <pkg> is a name, a name without its scope, or a directory. --help lists the packages. | | rxova-repo-config version | The release version script: changeset version, the root version synced from changeset.syncRootVersionFrom, then pnpm install --lockfile-only. | | rxova-repo-config version-pr | With pending changesets: git switch -C to VERSION_BRANCH (default changeset-release/<base>), runs VERSION_SCRIPT (default pnpm exec changeset version, with GITHUB_TOKEN taken from GH_TOKEN when only that is set), commits as COMMIT_MESSAGE (default chore: version packages), force-pushes, then edits the open pull request from that branch into the base or creates one, titled PR_TITLE (default chore: version packages), with a body listing each package whose version moved. The base is BASE_BRANCH, else the checked-out branch. Writes pull-request (the number, or empty) and changed=true\|false to GITHUB_OUTPUT. Publishes nothing. | | rxova-repo-config fix-lockfile | Repairs pnpm-lock.yaml after a bump that only edited a manifest (Dependabot in a pnpm workspace): pnpm install --lockfile-only --no-frozen-lockfile --ignore-scripts, then pnpm dedupe --ignore-scripts. Writes changed=true when git status shows pnpm-lock.yaml differs from the commit (an earlier install's edits included), else changed=false, to GITHUB_OUTPUT; exits 1 when pnpm or git fails. | | rxova-repo-config dependabot-update-type | Reads Dependabot's metadata from the first commit of BASE_SHA..HEAD_SHA and writes update-type (version-update:semver-major, -minor or -patch, the highest of a group; empty without metadata) and dependency-names (comma-separated) to GITHUB_OUTPUT. | | rxova-repo-config init [--dry-run] | Run once in a repository just created from a template: renames the template (the repository package.json points at) to this one in every tracked file, moves packages/example to packages/<repo>, copies the template's labels, runs Prettier on the files it rewrote, turns GitHub Pages on and adds the repository to the renovate installation on the owner organisation (or prints the manual step and opens the installation page in a browser), then prints the numbered steps left. In a private repository it adds a changeset for the renamed package, turns on auto-merge and head-branch deletion instead of Pages, adds the repository to the rxova-bot installation instead of renovate (or prints the manual step and opens the installation page in a browser; a classic personal access token with repo scope in GH_TOKEN lets it do this, the default gh login does not), and prints only what is still missing of the RXOVA_APP_ID and RXOVA_APP_PRIVATE_KEY secrets (Actions and Dependabot) and the all checks required check, instead of the npm steps. | | rxova-repo-config check-scope | Writes code-changed (false for a release commit or a documentation-only range, see Scope), docs-only and docs-changed to GITHUB_OUTPUT. Always exits 0. | | rxova-repo-config check-majors | Fails when the published packages (or majors.packages) are not on one major version. | | rxova-repo-config node-floor | Writes version (the single engines.node floor all published packages share) and packages to GITHUB_OUTPUT. | | rxova-repo-config pack-smoke [dir] | Packs the package, installs it in a scratch project, loads it, runs its bins and checks the tarball: see Pack smoke. | | rxova-repo-config check-exports [--profile p] | publint --strict, then attw --pack . with the profile from the flag or the package's repoConfig.exports.profile. | | rxova-repo-config post-publish-smoke | After a release, waits for npm to serve each version in PUBLISHED_PACKAGES (postPublish.registryTimeoutMinutes, 10 by default), installs them into a scratch project and loads them through import and require. | | rxova-repo-config check-llms [root] | Checks each published llms.txt: title, summary, sections, files, and its table against the source. See llms.txt. | | rxova-repo-config check-tsdoc | Fails a callable export of a published package's entry that has no TSDoc summary. | | rxova-repo-config check-banned | Fails a hand-written doc or README that names a removed API from docs.banned. | | rxova-repo-config check-snippets | Fails a ts, tsx, js or jsx fence in the READMEs and llms.txt files that does not parse. | | rxova-repo-config check-test-scripts | Fails a workspace that has a vitest.config.* and no test script, which no Turborepo task would run. | | rxova-repo-config check-file-size | Fails a tracked file over fileSize.max lines; the fileSize.allow list only shrinks. | | rxova-repo-config coverage-summary [path] | Appends the totals of coverage/coverage-summary.json (the json-summary reporter) to GITHUB_STEP_SUMMARY, or prints them. | | rxova-repo-config list-packages [--marker key] | Prints dirs=<json> and dirs_list=<words> for a CI matrix: the published packages, or those whose manifest sets key. --github-output appends to GITHUB_OUTPUT. |

Published packages are the directories under packages/ whose manifest is not private. Nothing needs to be listed by hand.

The reusable workflows in rxova/shared call the bin for you: commit-messages.yml runs check-scope, changeset-gate.yml runs check-changeset, and node-floor-smoke.yml runs node-floor and pack-smoke. The first two take a repo-config-command input, pnpm exec rxova-repo-config by default.

Pack smoke

pack-smoke fails when the tarball:

  • misses a files entry, the README or the license. Nested paths (assets/logo.svg) and globs (schemas/*.json) count when they match a file in the tarball.
  • misses a file the manifest points at: every exports target (.d.cts and .cjs included), main, module, types and each bin.
  • ships sources or tests: anything under src/, e2e/ or a __tests__ directory, or any *.test.* or *.spec.* file. A files entry that names that kind of path ("src", "e2e/fixtures.json") allows it; "dist" bringing in dist/a.test.js does not.
  • drops a 'use client' directive: when src/<entry>.ts(x) opens with one, the built dist/<entry>.js and .cjs must too, after any "use strict". Entries whose source has none are not checked.
  • has an exported stylesheet whose relative @import points at nothing in the tarball.

The package is imported and required by name; a package whose exports lists subpaths only is loaded through each subpath with a JavaScript target instead. Every bin must print a version for --version.

workspace: specs are resolved the way pnpm publish writes them. dependencies and optionalDependencies point at a packed tarball of the workspace package. peerDependencies become the published range (workspace:^ is ^<version>), and the peer's tarball is installed beside the package.

A package adjusts this in its own package.json:

{
  "repoConfig": {
    "packSmoke": {
      "load": "never",
      "bins": { "rxova-codemod": { "args": ["--help"], "expect": "input-otp-to-otp" } },
      "run": [
        {
          "bin": "rxova-codemod",
          "args": ["input-otp-to-otp", "fixture.tsx"],
          "fixture": { "path": "fixture.tsx", "contents": "import { OTPInput } from 'input-otp'" },
          "expect": ["OtpInput"]
        }
      ]
    }
  }
}

| Key | Effect | | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | load | auto (default) imports the package when it has a JavaScript entry. never skips the probe, for a package that ships TypeScript or Astro sources. | | bins | Replaces a bin's --version check with args and the text it must print (on stdout or stderr; semver when expect is unset). false runs no bin. | | run | Writes each fixture into the scratch project, runs the installed bin, and checks the fixture (or the output, without one) holds every expect string. |

llms.txt

check-llms applies repoConfig.llms to every published package; a package's own package.json#repoConfig.llms overrides api, requiredTerms, idPattern and idsFrom for it.

| Key | Values | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | api | exact (default): the ## API table and the entries name the same exports. documented: every documented name is exported. props: every ## Props name is a property in src/types.ts. none. | | entries | index (default) reads src/index.ts; subpaths also reads every src/<dir>/index.ts. | | sections | The ## headings required, A\|B for either. Default ["Install\|Use", "Docs"]; API is added for api: "exact". | | requiredTerms | Strings the file must contain: commands, URLs. | | idsFrom, idPattern | "path/to/types.ts#RULE_IDS" names an exported as const array; every id must appear, and any idPattern match that is not an id fails. | | rootIndex | true (default): the root llms.txt exists and links every package's file. |

Configuration

Everything is optional. Settings go in the root package.json under repoConfig; per-package settings (packSmoke, llms, exports.profile) go in that package's own package.json. An unknown key is an error, not a silent default.

| Key | Read by | Default | | ------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | verify.steps | verify, pre-push | The default gate under Quick start. A list replaces it entirely. | | verify.steps[].group | verify --plan | None. Steps sharing a group run in one fan-out job, in list order. Local verify ignores it. | | verify.steps[].split | verify --plan, verify --filter | None. true or { "max": n } (default 8) on a step whose command runs turbo run <task…>: fan-out splits it into per-package jobs. Never with group. Local verify ignores it. | | changeset.singlePackage | check-changeset, lint-changesets | false. true requires each changeset to name exactly one package. | | changeset.scope | check-changeset | code: a package's code changed, markdown and tests aside. shipped: anything its tarball ships. | | changeset.roots | add-changeset | ["packages", "apps"] | | changeset.aliasPrefix | add-changeset | None. journey- lets core name @rxova/journey-core. | | changeset.includePrivate | add-changeset, check-changeset | false: private packages are neither offered nor required to have a changeset. true offers them to add-changeset and makes check-changeset require a changeset when one changes (unless the PR is labelled skip-changeset), for a repository whose packages are all private. | | changeset.syncRootVersionFrom | version | None: the root version is left alone. | | majors.packages | check-majors | Every published package. | | tsdoc.entries, tsdoc.exclude | check-tsdoc | packages/<dir>/src/index.ts; no exclusions. | | docs.root | check-banned | apps/docs/src/content/docs | | docs.banned | check-banned | None. { name, pattern, flags? }, pattern a regex source. | | docs.allow, docs.exclude | check-banned | None. Globs under docs.root: allowed to name a banned API, or not scanned at all. | | docs.readmes | check-banned | true: the root README and every packages/<dir>/README.md are scanned too. | | snippets.include | check-snippets | ["README.md", "packages/*/README.md", "packages/*/llms.txt"]: globs, files, directories. | | snippets.skipInfo | check-snippets | ["live"]: a fence whose info string holds one of these words is skipped. | | packages.marker | list-packages | None: the published packages. | | postPublish.importPattern | post-publish-smoke | None: every published package is imported. A regex source. | | postPublish.peers | post-publish-smoke | None. Installed beside the packages, the way a consumer provides peers. | | postPublish.registryTimeoutMinutes | post-publish-smoke | 10. How long to wait for npm to serve each published version before failing. | | llms | check-llms | See llms.txt. | | scope.ignore | check-scope | ["**/*.md", "**/*.mdx"]: documentation, see Scope. | | scope.keep | check-scope | packages/*/*/** and test and fixture folders: code even where ignore matches. | | scope.site | check-scope | ["apps/docs/**"]: the docs site, reported as docs-changed. | | testScripts.globs | check-test-scripts | ["packages/*", "apps/*"] | | fileSize.max | check-file-size | 500 lines. | | fileSize.extensions | check-file-size | ts, tsx, js, mjs, cjs, astro, css, yaml, yml, json | | fileSize.ignore | check-file-size | ["pnpm-lock.yaml"] | | fileSize.allow | check-file-size | None. Files over the limit today; an allowed file back under the limit fails. |

A full example:

{
  "repoConfig": {
    "verify": {
      "steps": [
        { "name": "audit", "command": "pnpm audit:check", "skipOnRelease": true },
        { "name": "lint", "command": "pnpm lint" },
        { "name": "changesets", "command": "rxova-repo-config lint-changesets" },
        { "name": "format", "command": "pnpm format:check", "group": "static" },
        { "name": "dependency versions", "command": "pnpm sherif:check", "group": "static" },
        { "name": "unit tests", "command": "pnpm exec turbo run test", "split": { "max": 8 } }
      ]
    },
    "changeset": {
      "singlePackage": true,
      "scope": "shipped",
      "roots": ["packages", "apps"],
      "aliasPrefix": "journey-",
      "includePrivate": false,
      "syncRootVersionFrom": "@rxova/journey-core"
    },
    "majors": { "packages": ["@rxova/journey-core", "@rxova/journey-react"] },
    "tsdoc": { "entries": { "@rxova/journey-core": "packages/core/src/index.ts" }, "exclude": [] },
    "docs": {
      "root": "apps/docs/src/content/docs",
      "banned": [{ "name": "useApi", "pattern": "\\buseApi\\b" }],
      "allow": ["**/releases.md"],
      "exclude": ["**/api/reference/**"],
      "readmes": true
    },
    "snippets": { "include": ["README.md", "packages/*/README.md"], "skipInfo": ["live"] },
    "packages": { "marker": "rxova.slug" },
    "postPublish": { "importPattern": "^@rxova/react-", "peers": { "react": "^19" } },
    "llms": { "api": "documented", "entries": "subpaths" },
    "scope": {
      "ignore": ["**/*.md", "**/*.mdx"],
      "keep": ["packages/*/*/**"],
      "site": ["docs/**"]
    },
    "testScripts": { "globs": ["packages/*", "apps/*"] },
    "fileSize": { "max": 500, "ignore": ["pnpm-lock.yaml"], "allow": [] }
  }
}
  • verify.steps[].skipOnRelease skips a step on the release pull request (GITHUB_HEAD_REF=changeset-release/main). On GitHub Actions each step folds into its own log group.
  • verify.steps[].group and split shape verify --plan, the matrix of the fan-out: true mode of the verify.yml workflow: a step is one job, a group is one job where its first step stands, and a split step runs <command> --dry=json and deals the packages that miss the cache, heaviest first by input count, into at most max jobs, each verify --only <step> --filter <packages>; the packages that hit join the lightest job, and a step with no miss is one job that replays the cache. Its command should end with the turbo run, since --dry=json and --filter are appended to it. Jobs share artifacts through a Turbo remote cache.
  • With changeset.scope: "shipped", a README or llms.txt edit needs a changeset too; src/ and tsdown.config.* count when files lists dist.
  • add-changeset leaves out the packages in .changeset/config.json#ignore.

Scope

check-scope tells CI which jobs a range needs. It writes code-changed=false, and the build, test and package jobs gated on it skip, when every changed file is one of:

  • release bookkeeping: a changeset, a changelog, or a package.json whose only edit is its version;
  • documentation: a path scope.ignore matches and scope.keep does not, that the range did not delete (a check may expect the file, as pack-smoke expects a README).

The default keep leaves Markdown below a package's top level (content a package ships, which its tests read) and in test and fixture folders counted as code; a package's README stays documentation. llms.txt is not Markdown, so an edit to it runs everything. docs-only=true marks a documentation range, for a light job such as docs-checks.yml (formatting, plus check-snippets or check-banned where a repository runs them), and docs-changed=true a range that touched scope.site, so the docs site still builds. A range that cannot be read runs everything, and "ignore": [] turns the documentation skip off.

Presets

One preset per tool. Repository differences are options, not copies.

| Import | Use | | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | @rxova/repo-config/eslint | rxova(options, ...extra): the flat config, see ESLint. | | @rxova/repo-config/prettier | Semicolons, double quotes, printWidth: 100, trailingComma: "all", arrowParens: "always", with prettier-plugin-astro built in for *.astro. | | @rxova/repo-config/lint-staged | ESLint (--fix --no-warn-ignored) then Prettier over staged code (.astro included), Prettier over JSON, CSS, SCSS, Markdown, MDX, YAML and HTML. | | @rxova/repo-config/tsdown | baseBuildConfig, dualBuildConfig, reactBuildConfig: see tsdown. | | @rxova/repo-config/vitest | baseVitestConfig(options): 95% per-file coverage; @/ is <root>/src; see Vitest. | | @rxova/repo-config/playwright | basePlaywrightConfig(options) and astroPreview(port); see Playwright. | | @rxova/repo-config/knip | baseKnipConfig(options); see Knip. | | @rxova/repo-config/commitlint | @commitlint/config-conventional with no length limits, plus the rename type. | | @rxova/repo-config/changelog | @changesets/changelog-github without the "Thanks @user!" line; the pull-request and commit links stay. | | @rxova/repo-config/tsconfig.base.json | Strict TypeScript for ESM libraries: ES2023, no DOM, bundler resolution, verbatimModuleSyntax, exactOptionalPropertyTypes, noUncheckedIndexedAccess, noEmit. | | @rxova/repo-config/tsconfig.dom.json | The base plus DOM and DOM.Iterable. | | @rxova/repo-config/tsconfig.react.json | The dom preset plus jsx: "react-jsx". | | @rxova/repo-config/tsconfig.node.json | Scripts Node runs with type stripping: NodeNext, allowImportingTsExtensions, erasableSyntaxOnly, Node types. |

The presets that ESLint, Prettier, lint-staged, changesets and the commit hook load before anything is built ship as plain JavaScript, so they work in a fresh clone.

ESLint

rxova(options, ...extra) returns a flat config: @eslint/js recommended, typescript-eslint recommendedTypeChecked with projectService on .ts/.tsx/.mts/.cts, and these rules on TypeScript: no-unused-vars (_-prefixed arguments allowed), consistent-type-imports (inline fixes), no-explicit-any and no-console. Build output, caches, .claude/, test reports and tool config files (*.config.*, knip.*) are ignored. There are no formatting, import-path or project-structure rules: add them through rules, extends or extra.

| Option | Default | Effect | | ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | tsconfigRootDir | — | Required: import.meta.dirname. | | strict | false | strictTypeChecked instead of recommendedTypeChecked. | | react | false | true or { files, hooks, a11y, additionalHooks, version }: eslint-plugin-react (+ JSX runtime), react-hooks and jsx-a11y, on **/*.{tsx,jsx} unless files widens it. | | astro | false | eslint-plugin-astro recommended, browser globals and the tsconfig root pinned on .astro files. | | node, browser | false | Globals on every file (true) or on the given globs. | | tests | false | true or { files }: vitest, jest, browser and Node globals and the test relaxations (no-unsafe-*, no-non-null-assertion, no-console, …) on test files, fixtures and e2e/. | | ignores | [] | Global ignores added to the defaults. | | consoleAllowed | [] | Globs where no-console is off: CLIs and scripts. | | extends | [] | Configs merged into the TypeScri