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

rlint

v0.6.0

Published

Catch rendered layout bugs automatically - no screenshots needed. Like ESLint for your rendered UI.

Readme

rlint

Catch rendered layout bugs automatically — no screenshots needed.

Like ESLint, but for your rendered UI. Renderlint detects horizontal overflow, covered buttons, tiny touch targets, and other structural bugs that slip through code review.

rlint check http://localhost:3000

❌ OVERFLOW Horizontal overflow detected (page scrolls 740px beyond viewport)
   └─ Element: div.hero-banner
   └─ Fix: Add overflow-x: hidden or check for elements with fixed widths

❌ CLICKABILITY Interactive element is covered by another element
   └─ Element: button.submit-btn
   └─ Covered by: div.modal-backdrop
   └─ Fix: Check z-index or remove covering element

⚠️  TOUCH-TARGETS Touch target too small: 32x28px (min: 44x44px)
   └─ Element: a.nav-link
   └─ Fix: Add min-width: 44px and min-height: 44px

──────────────────────────────────────────────────
Results: 2 errors, 1 warning, 47 passed
──────────────────────────────────────────────────

The Problem

Layout bugs are invisible in code review. Your PR looks fine, tests pass, but then:

  • The page scrolls horizontally on mobile
  • A modal backdrop covers your buttons
  • Touch targets are too small for actual fingers

These aren't styling issues — they're structural bugs that can be detected programmatically using getBoundingClientRect(), getComputedStyle(), and elementFromPoint().

Installation

# Install globally (recommended — makes `rlint` available everywhere)
npm install -g rlint

# Or use without installing
npx rlint check https://example.com

# Or install as a dev dependency
npm install --save-dev rlint

No extra setup. Renderlint uses your system Chrome — no 150MB Chromium download. If Chrome isn't installed, Chromium is downloaded automatically on first run.

Note: The first run may be slower if Chromium needs to be downloaded (~150MB). Subsequent runs use the cached browser.

Quick Start

# Dev proxy — check pages as you browse (handles auth automatically)
rlint dev http://localhost:5173

# Check any URL
rlint check https://example.com

# Check with auth (setup script logs in first)
rlint check --setup ./login.js http://localhost:3000/dashboard

# Mobile testing (portrait + landscape at 375x667)
rlint check --mobile http://localhost:3000

# Auto-detect framework and start dev server
rlint dev

Dev Proxy (Recommended for Development)

The dev proxy solves the auth problem. Instead of opening a separate headless browser (which has no session), rlint injects check scripts into your existing browser. You're already logged in — auth is handled automatically.

# Start your dev server, then:
rlint dev http://localhost:5173

# Proxy starts on http://localhost:3100
# Open that URL in your browser and browse normally
# rlint checks every page you visit and reports issues in your terminal

Every page you visit is checked automatically. Navigate to /dashboard, /settings, /admin — rlint reports issues for each page in real-time. No cookies, no setup scripts, no configuration.

rlint dev (proxy mode)
Target: http://localhost:5173

Proxy running at http://localhost:3100
Open http://localhost:3100 in your browser.
Browse your app normally — rlint checks every page you visit.
Auth is handled automatically through your browser session.

  ✓ / @ 1280x720 — no issues
  ✗ /dashboard @ 1280x720 — 1 error, 2 warnings
    ✗ [overflow] Horizontal overflow detected (page scrolls 120px beyond viewport)
      → div.data-table
    ⚠ [touch-targets] Touch target too small: 32x28px (min: 44x44px)
      → a.nav-link

How the proxy works

  1. You start rlint dev http://localhost:5173 — a reverse proxy starts on port 3100
  2. Open http://localhost:3100 in your browser — it forwards everything to your dev server
  3. For HTML pages, rlint injects a small check script that runs all 6 checks directly in your browser
  4. Results are sent back to rlint and displayed in your terminal
  5. SPA navigation (pushState/popstate) and dynamic content changes trigger re-checks automatically
  6. WebSocket connections (Vite HMR, etc.) pass through — hot reload works normally

Checks

| Check | Severity | What it catches | |-------|----------|-----------------| | overflow | error | Horizontal scrollbars from content wider than viewport | | clickability | error | Buttons/links covered by other elements — checks center + all 4 corners | | touch-targets | warning | Elements smaller than 44×44px (WCAG 2.5.5) + adjacent targets with <8px gap | | visibility | warning | Interactive elements that are invisible or off-screen | | text-overflow | warning | Text clipped without proper ellipsis handling | | viewport-meta | warning | Missing or misconfigured viewport meta tag (mobile rendering) |

Framework Support

Renderlint auto-detects your framework and handles hydration:

# Auto-detect and start dev server
rlint dev --routes /,/about,/contact

# Specify framework manually
rlint dev --framework nextjs --routes /,/api/health

Supported: Next.js, SvelteKit, Vite, Remix, Astro, Nuxt, Create React App

Library Usage

import { checkPage } from 'rlint';
import { launchBrowser } from 'rlint/browser';

const browser = await launchBrowser();
const page = await browser.newPage();
await page.goto('http://localhost:3000');

const results = await checkPage(page);
console.log(results.summary);
// { passed: 47, errors: 1, warnings: 2 }

await browser.close();

MCP Server (for AI Agents)

Renderlint includes an MCP server so AI agents can check pages for layout bugs programmatically.

Claude Code

claude mcp add rlint -- npx rlint-mcp

Or add to your project's .mcp.json:

{
  "mcpServers": {
    "rlint": {
      "command": "npx",
      "args": ["rlint-mcp"]
    }
  }
}

Claude Desktop

Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):

{
  "mcpServers": {
    "rlint": {
      "command": "npx",
      "args": ["rlint-mcp"]
    }
  }
}

Cursor

Add to .cursor/mcp.json in your project:

{
  "mcpServers": {
    "rlint": {
      "command": "npx",
      "args": ["rlint-mcp"]
    }
  }
}

Available MCP Tools

| Tool | Description | |------|-------------| | check_page | Check a URL for layout issues. Automatically uses proxy cache if rlint dev is running. | | check_html | Check raw HTML content directly | | check_file | Check a local HTML file by path | | get_dev_results | Get cached results from the running dev proxy (for authenticated pages) | | screenshot | Take a screenshot of a URL or element (returns base64 PNG) |

All check tools accept optional parameters:

  • viewport ({ width, height }) — custom viewport size
  • checks (array) — specific checks to run: overflow, clickability, touch-targets, text-overflow, visibility, viewport-meta
  • mobile (boolean) — test at mobile viewports (375x667 portrait + 667x375 landscape)

Results include element selectors, dimensions, and fix hints.

Authenticated Pages with MCP

When rlint dev proxy is running, the MCP tools automatically use it:

  1. check_page checks the proxy cache first — if the developer has already visited the page, results are returned instantly
  2. get_dev_results returns all cached results from pages the developer has browsed
  3. If the proxy isn't running, check_page falls back to headless Chrome (works for public pages)

This means AI agents can check authenticated pages without needing credentials — the developer's browser session handles auth.

For LLMs: Using rlint as a CLI Tool

If you're an LLM/AI agent with shell access, you can use rlint directly from the command line to validate UI you've built or modified.

Quick reference

# Install globally (one-time setup)
npm install -g rlint

# Check a running dev server
rlint check http://localhost:3000 --format json

# Mobile testing (portrait + landscape, recommended after UI changes)
rlint check --mobile --format json http://localhost:3000

# Check specific routes at mobile viewport
rlint check --viewport 375x667 http://localhost:3000 http://localhost:3000/about

# Check with JSON output (easiest to parse)
rlint check --format json http://localhost:3000

# Run only specific checks
rlint check --only overflow,clickability http://localhost:3000

# Auto-detect framework, start dev server, check routes
rlint dev --routes /,/about,/settings --format json

Interpreting results

rlint exits with code 1 if errors are found (code 0 if clean). Use --format json for structured output:

{
  "url": "http://localhost:3000",
  "summary": { "passed": 47, "errors": 1, "warnings": 2 },
  "issues": [
    {
      "check": "overflow",
      "severity": "error",
      "message": "Horizontal overflow detected",
      "element": { "selector": "div.hero-banner" },
      "fixHint": "Add overflow-x: hidden or check for elements with fixed widths"
    }
  ]
}

Recommended workflow for LLMs

  1. Make your UI changes
  2. Ensure the dev server is running
  3. Run rlint check --format json http://localhost:3000 on affected routes
  4. Parse the JSON output — fix any issues using the fixHint and element.selector fields
  5. Re-run to verify fixes

For authenticated pages: if the MCP server is available, use the get_dev_results tool (requires rlint dev proxy running). Otherwise, use rlint check --setup ./login.js with a setup script.

Available checks

  • overflow — Horizontal scrollbars from content wider than viewport
  • clickability — Buttons/links covered by other elements (checks center + 4 corners)
  • touch-targets — Elements smaller than 44x44px + adjacent targets with <8px gap
  • text-overflow — Text clipped without ellipsis handling
  • visibility — Interactive elements that are invisible or off-screen
  • viewport-meta — Missing or misconfigured viewport meta tag

Configuration

// rlint.config.js
export default {
  checks: {
    overflow: { horizontal: true },
    touchTargets: { minWidth: 44, minHeight: 44 },
    clickability: { checkCorners: true },
    textOverflow: { allowEllipsis: true },
  },
  ignore: ['.tooltip', '[data-rlint-ignore]'],
};

Ignoring Elements

<!-- Skip specific elements -->
<input type="checkbox" data-rlint-ignore>

CI Integration

# .github/workflows/rlint.yml
name: Renderlint Check
on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm run build
      - run: npm install -g rlint
      - run: npm start & npx wait-on http://localhost:3000
      - run: rlint check --fail-on warning http://localhost:3000

Checking Authenticated Pages in CI

Use --setup to run a login script before checks. The script receives a Puppeteer page and can perform any browser actions. Cookies persist for all subsequent checks.

rlint check --setup ./tests/login.js http://localhost:3000/dashboard http://localhost:3000/settings
// tests/login.js
export default async (page) => {
  await page.goto('http://localhost:3000/login');
  await page.type('input[name="email"]', '[email protected]');
  await page.type('input[name="password"]', 'password');
  await page.click('button[type="submit"]');
  await page.waitForNavigation();
};

Tip: Renderlint uses system Chrome. If unavailable, Chromium is downloaded to ~/.cache/rlint on first run. Cache this directory in CI for faster builds.

CLI Reference

rlint dev [url]                 Start proxy (with URL) or framework mode (without)
  --proxy-port <port>          Proxy port (default: 3100)
  -r, --routes <routes>        Routes to check (framework mode, default: /)
  -p, --port <port>            Dev server port (framework mode)
  --framework <name>           Framework override
  --mobile                     Test mobile viewports (375x667 + 667x375)
  --no-start-server            Use existing dev server

rlint check <urls...>
  --setup <script>             Run a setup script before checks (e.g., login)
  -v, --viewport <size>        Viewport size (e.g., 375x667,1920x1080)
  -f, --format <format>        Output: text, json, junit
  -o, --only <checks>          Run specific checks only
  -i, --ignore <selectors>     Ignore matching elements
  -c, --config <path>          Config file path
  --fail-on <severity>         Exit code 1 on: error, warning
  --mobile                     Test mobile viewports (375x667 + 667x375)
  --headed                     Show browser window
  --wait-for-hydration         Wait for SPA hydration

How It Works

Renderlint doesn't compare screenshots. Instead, it queries the DOM:

// Overflow detection
document.documentElement.scrollWidth > document.documentElement.clientWidth

// Covered element detection
document.elementFromPoint(x, y) !== expectedElement

// Touch target detection
element.getBoundingClientRect().width < 44

These checks are deterministic, fast, and don't require human review.

Why Not Visual Regression?

Visual regression (screenshot comparison) catches everything but requires human review for every change. Renderlint catches structural bugs that are objectively wrong:

| Visual Regression | Renderlint | |-------------------|------------| | Catches color changes | Catches layout bugs | | Requires baseline images | No baselines needed | | Needs human review | Fully automated | | Slow (image comparison) | Fast (DOM queries) |

Use both! Visual regression for design fidelity, Renderlint for structural correctness.

License

MIT