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

rsc-contract

v0.1.1

Published

Contracts, diagnostics and budgets for React Server Components boundaries.

Readme

rsc-contract

Contracts, diagnostics and budgets for React Server Components boundaries.

rsc-contract is a static analysis tool that helps you understand and control what crosses the Server → Client boundary in React Server Components (RSC): which modules are client-side, which values cross the boundary, how big the estimated payload is, and whether that payload regressed since your baseline.

npm install -D rsc-contract
npx rsc-contract check

Honesty note. This is static, best-effort analysis. It cannot prove every runtime property of JavaScript. Findings are classified as safe / unsafe / unknown, and unknown is never reported as an error. Payload numbers are static estimates, clearly labeled as such — they are not runtime Flight measurements.

What is an RSC boundary?

In React Server Components, the module graph is split in two:

  • Server modules run only on the server (they may use databases, secrets, Node.js APIs).
  • Client modules (files with the 'use client' directive, plus everything they import) run in the browser.

When a server component renders a client component, the props cross a serialization boundary: the React Flight protocol must serialize them. Functions, class instances, WeakMaps, database clients and Node.js streams cannot cross — and huge props silently grow your RSC payload.

rsc-contract makes those boundaries and their costs visible, checked and enforced in CI.

CLI

rsc-contract check              # run rules, report diagnostics (exit 1 on errors)
rsc-contract analyze            # diagnostics + payload estimate + budgets
rsc-contract analyze --output .rsc-contract/report.json
rsc-contract diff .rsc-contract/report.json
rsc-contract graph              # print the Server/Client module graph
rsc-contract --help | --version

Formats: --format pretty (default), --format json (versioned, machine readable), --format ci (single-line file:line:col CODE severity message, IDE/GitHub friendly).

Exit codes: 0 — clean; 1 — errors or budget exceeded; 2 — usage error.

Example output

RSC001

Value cannot safely cross the Server to Client boundary.

Component: ProfileCard
Prop: onSave

Why:
Functions cannot cross the Server -> Client boundary.

Suggestion: Pass a serializable DTO instead (plain objects, strings, numbers, booleans).

Configuration

// rsc-contract.config.mjs
import { defineConfig } from 'rsc-contract';

export default defineConfig({
  include: ['src/**/*.{ts,tsx}'],
  exclude: ['node_modules', '.next'],
  budgets: {
    rscPayload: '200kb',       // max estimated RSC payload
    clientBoundary: '50kb',    // max estimated payload per boundary
    clientDependency: '150kb', // max estimated package footprint in client graph
  },
  rules: {
    serialization: 'error',
    serverOnlyImport: 'error',
    largeBoundary: 'warning',
  },
  tsconfig: './tsconfig.json', // path aliases (also auto-discovered)
});

.json and .mjs/.cjs/.js configs are supported; .ts configs work on Node versions with native TypeScript support.

Rules

| Code | Rule | Default | Detects | |------|------|---------|---------| | RSC001 | serialization | error | Values crossing the boundary that Flight cannot serialize (functions, class instances, WeakMap/WeakSet, symbols, server objects) | | RSC002 | serverOnlyImport | error | Node built-ins and known server packages (db drivers, etc.) imported from the client graph | | RSC003 | boundaryAnalysis | info | Server→Client boundary map; client modules importing server modules (error) | | RSC004 | largeBoundary | warning | Boundary prop payload above budgets.clientBoundary (estimated) | | RSC005 | clientDependency | warning | Heavy third-party packages in the client graph (estimated footprint) | | RSC006 | secretLeak | warning | Secret-bearing props (apiKey, token, …) crossing the boundary. Values are always redacted |

Codes are stable and never reused for a different problem.

Budgets

RSC budget exceeded

Budget:  200 KB
Actual:  384 KB
Difference: +184 KB (+92%)

Exceeding a budget in check/analyze/diff produces a non-zero exit code — safe to enforce in CI.

Diff (baseline comparisons)

npx rsc-contract analyze --output .rsc-contract/report.json
git add .rsc-contract/report.json
# later, or in CI after a PR changes code:
npx rsc-contract diff .rsc-contract/report.json

The diff compares payload estimates, client dependencies, boundaries and diagnostics between the baseline snapshot and the current analysis.

CI (GitHub Actions)

- run: npm ci
- run: npx rsc-contract check
- run: npx rsc-contract analyze --output .rsc-contract/report.json
- run: npx rsc-contract diff .rsc-contract/base.json

See examples/ci and .github/workflows.

Limits (please read)

  • Static, best-effort. Values whose origin cannot be determined statically are reported as unknown with info severity, never as errors.
  • Payload numbers are estimates derived from the source text of boundary props and the client module graph. They are useful for trends and budgets, not byte-accurate Flight measurement. Implement the RscPayloadProvider interface to plug in real runtime measurements.
  • Package footprints are approximations of on-disk size; tree-shaking and bundling are not modeled.
  • 'use client' is detected by directive (with comments/whitespace allowed before it), including through barrel re-exports, aliased paths and dynamic imports. Framework-specific conventions (e.g. Next.js route groups) are not modeled yet.

Architecture

See docs/architecture.md for the pipeline, the parser choice (TypeScript Compiler API), the rule engine and how to add your own rules via createRule / registerRule.

Framework support

The core is framework-agnostic. The built-in node adapter resolves modules with tsconfig paths and standard node_modules resolution — it works for Next.js App Router, React Router RSC mode, and custom setups that follow the 'use client' convention. Dedicated adapters (deeper route/payload integration) are planned; none are included yet.

Contributing

npm install
npm test
npm run typecheck
npm run build

Fixtures live in fixtures/ and run as part of the test suite. New rules need a fixture that exercises real behavior, not just the happy path.

License

MIT