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

@dreamtree-org/config

v0.2.0

Published

Shared ESLint (incl. Dreamtree design-lint), TypeScript, Prettier, Vitest, knip and Playwright presets for every Dreamtree product — one line per tool, per-stack defaults.

Readme

@dreamtree-org/config

Replaces the ESLint, TypeScript, Prettier, Vitest, knip and Playwright config files (and the qc:* scripts) that were copy-pasted into every Dreamtree product. Each tool gets one line per app.

60-second start

npm i -D @dreamtree-org/config

| Tool | In the app | |---|---| | ESLint | eslint.config.mjs: import dreamtree from '@dreamtree-org/config/eslint'; export default dreamtree({ stack: 'next' }); | | TypeScript | tsconfig.json: { "extends": "@dreamtree-org/config/tsconfig/next.json" } (or node.json, vite-react.json) | | Prettier | package.json: "prettier": "@dreamtree-org/config/prettier" | | Vitest | vitest.config.ts: import { dreamtreeVitest } from '@dreamtree-org/config/vitest'; export default dreamtreeVitest(); | | knip | knip.config.ts: import { dreamtreeKnip } from '@dreamtree-org/config/knip'; export default dreamtreeKnip({ stack: 'next' }); | | Playwright | playwright.config.js: export default dreamtreePlaywright({ baseURL, webServer: { env } }) | | qc scripts | "qc:cycles": "dreamtree-qc cycles", "qc:baseline": "dreamtree-qc baseline", "qc:deadcode": "knip" |

The tools themselves are optional peer dependencies: install only what your stack uses.

| Stack | Peers it needs | |---|---| | next | eslint, eslint-config-next, eslint-config-prettier, typescript | | express | eslint, @eslint/js, globals; eslint-plugin-sonarjs (used when installed) | | vite-react | eslint, @eslint/js, globals, eslint-plugin-react; eslint-plugin-react-hooks (used when installed) | | any + typescript: true | typescript-eslint | | Vitest / Playwright / knip / Prettier / qc | vitest / @playwright/test / knip / prettier / madge |

A missing peer fails with the command to fix it: dreamtree({ stack: 'next' }): "eslint-config-next" is not installed — run \npm i -D eslint-config-next` in the app.`

ESLint — dreamtree(options)

| Key | Type | Default | Meaning | |---|---|---|---| | stack | 'next' \| 'express' \| 'vite-react' | required | Which preset. | | ignores | string[] | [] | Appended to the stack's global ignores. | | overrides | object[] | [] | Flat-config objects appended after the preset, e.g. { files: ['lib/mock/**'], rules: { 'max-lines': 'off' } }. | | legacyFiles | string[] | [] | Files whose error rules drop to warnings (your eslint.legacy.mjs list). Never add to it. | | relaxedFiles | string[] | tests, scripts, commands | Files with size/complexity/any/console rules off. Replaces the default. | | nativeDialogs | boolean | on for next, vite-react | Ban alert/confirm/prompt, including window.confirm, self.prompt and const w = window. | | dialogHint | string | 'use the twreact-ui Dialog and Toast' | What the lint message tells people to use instead. | | serverOnlyImports | string[] | [] | next: appended to the modules client code may not import (knex, mysql2, ioredis, bullmq, @/lib/tenancy/*, @/lib/platform/*, @/lib/jobs/*, @/models/*). | | serverDirs | string[] | ['lib','models','app/api'] | next: no-console is an error here. | | domainDirs | string[] | ['lib'] | next: .ts functions capped at 40 lines (components keep 60). | | clientDirs | string[] | ['components','lib/hooks'] | next: may not import server-only modules. | | sonar | boolean | true | express: add sonarjs quality gates when the plugin is installed. | | module | 'cjs' \| 'esm' | 'cjs' | express: source type of server code. | | client | string | — | express: a Vite/React folder in the same repo (e.g. 'client'); gets the vite-react rules. | | typescript | boolean | false | express / vite-react: add typescript-eslint strict rules. | | design | boolean \| object | false | Add the Dreamtree design rules (see below). true, or the dreamtreeDesign options. |

Design rules — design: true or @dreamtree-org/config/eslint/design

The rules in twreact-ui's DESIGN.md, as lint. Every message names the fix, so people and AI agents (Dreamtree Studio's validate_screen) can correct the code from the lint output alone.

| Rule | Catches | Message suggests | |---|---|---| | dreamtree-design/no-raw-colors | bg-blue-600, text-slate-500, border-[#19a249], style={{ color: '#f00' }} in class strings (className, cn(), clsx(), cva()) | the token class (bg-primary-600, text-secondary-500) or a role (bg-surface, text-muted) | | dreamtree-design/no-arbitrary-values | text-[11px], w-[312px] (grid templates allowed) | text-micro, text-xs, rounded-card, or the Tailwind scale | | dreamtree-design/allowed-imports | other UI kits (@mui, antd, @radix-ui, react-icons, …), or anything outside allowImports when set | twreact-ui components and blocks, lucide-react | | dreamtree-design/require-states (warn) | a default-exported page that renders a list with no loading, empty or error branch | LoadingState, EmptyState, ErrorState | | native dialogs | alert / confirm / prompt | ConfirmDialog and Toast |

// Product: opt in next to the stack preset (start with severity 'warn' and ratchet).
export default dreamtree({ stack: 'next', design: { severity: 'warn' } });

// Standalone (Dreamtree Studio prototypes): strict import allowlist.
import { dreamtreeDesign } from '@dreamtree-org/config/eslint/design';
export default dreamtreeDesign({ allowImports: ['react', '@dreamtree-org/twreact-ui', 'lucide-react'] });

Spot check on 20 Oct 2026: school360 → 4,163 raw colours, 1,322 arbitrary values, 30 alert(); PracticePro → 1,646 raw colours, 40 arbitrary values.

What each stack enforces

| | next | express | vite-react | |---|---|---|---| | Base | eslint-config-next core-web-vitals + typescript, eslint-config-prettier | @eslint/js recommended, sonarjs recommended, Node globals | @eslint/js recommended, React JSX, browser globals | | Function size | 60 lines (40 in lib/**/*.ts) | 120 | 120 | | Complexity | 12, max-params 3, max-depth 3 | 15 (+ sonar cognitive 15) | 15 | | File size | 400 lines, 250 for .tsx | — | — | | Empty catch | error | allowed (best-effort swallows) | allowed | | any | error | — (error with typescript: true) | — (error with typescript: true) | | Native dialogs | error | — | error | | Other | no as unknown as, no thrown object literals, no server-only imports in client code, no console in server code | no-eval family, no thrown literals | no module.exports in Vite src, no-eval family |

TypeScript

tsconfig/next.json (Next apps), tsconfig/node.json (TS services: strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes), tsconfig/vite-react.json (node.json + DOM, react-jsx, vite/client, noEmit).

paths, include and exclude resolve relative to the file that declares them, so they stay in the app:

{
  "extends": "@dreamtree-org/config/tsconfig/next.json",
  "compilerOptions": { "paths": { "@/*": ["./*"] } },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

Prettier

"prettier": "@dreamtree-org/config/prettier" — printWidth 120, double quotes, trailing commas (Next apps). "prettier": "@dreamtree-org/config/prettier/single-quote" — printWidth 100, single quotes (TS monorepos). Keep .prettierignore in the app; Prettier has no shared ignore.

Vitest — dreamtreeVitest(options)

| Key | Type | Default | Meaning | |---|---|---|---| | root | string | process.cwd() | Alias targets are relative to this. Pass __dirname. | | environment | string | 'node' | 'jsdom' for React client tests. | | include | string[] | ['**/*.test.ts','**/*.test.tsx'] | | | exclude | string[] | [] | Appended to node_modules, .next, dist, coverage, scripts, graphify-out. | | alias | Record<string,string> | { '@': '.' } | Mirror your vite.config.js aliases here. | | serverOnlyStub | boolean | true | Alias server-only to an empty module shipped by this package. | | globals, setupFiles, plugins | | — | Passed through. | | timeout | number | — | Sets both testTimeout and hookTimeout. | | coverage | object \| false | v8 over lib/**, models/** | Merged into the defaults. | | test, resolve | object | — | Any other Vitest keys, merged last. |

knip — dreamtreeKnip(options)

knip.json cannot extend, so use knip.config.ts:

import { dreamtreeKnip } from '@dreamtree-org/config/knip';
export default dreamtreeKnip({ stack: 'next', entry: ['korm-mcp.config.cjs'], ignoreDependencies: ['archiver'] });

entry and ignore are appended to the stack base (next: models/**/*.js, lib/api.ts); any other knip key passes through.

Playwright — dreamtreePlaywright(options)

import { dreamtreePlaywright } from '@dreamtree-org/config/playwright';
const PORT = process.env.E2E_PORT || 5002;
export default dreamtreePlaywright({
  baseURL: `http://localhost:${PORT}`,
  webServer: { env: { PORT: String(PORT), NODE_ENV: 'test' } },
});

Defaults: testDir: './tests/e2e', 30 s timeout, serial, github reporter on CI else list, trace: 'on-first-retry', desktop (1440×900) + mobile (Pixel 7) projects, webServer npm start waiting on ${baseURL}/health. Every key can be overridden (mobile: false, projects, use, …).

Recipes

Next (firepro, CampaignPro, procurementpro)

import dreamtree from '@dreamtree-org/config/eslint';
import legacyFiles from './eslint.legacy.mjs';
export default dreamtree({ stack: 'next', serverOnlyImports: ['firebase-admin'], legacyFiles });

Express + Vite client (taskpro, venturepro, billpro, ai-agent-builder) — CommonJS root:

const { dreamtree } = require('@dreamtree-org/config/eslint');
module.exports = dreamtree({ stack: 'express', client: 'client', ignores: ['schema/sync.json'] });

client/vitest.config.js:

import react from '@vitejs/plugin-react';
import { dreamtreeVitest } from '@dreamtree-org/config/vitest';
export default dreamtreeVitest({
  root: __dirname, environment: 'jsdom', globals: true, plugins: [react()],
  include: ['src/**/*.test.{js,jsx}'], alias: { '@': 'src', '@api': 'src/api' },
  serverOnlyStub: false, coverage: false, timeout: 30_000,
});

TS monorepo (fitweavepro, runloompro) — dreamtree({ stack: 'express', module: 'esm', typescript: true, sonar: false }), extends: "@dreamtree-org/config/tsconfig/node.json", "prettier": "@dreamtree-org/config/prettier/single-quote".

What it deliberately does NOT do

  • No product rules. Ticket-specific bans (appforge's PRE-110 import walls, runloompro's Temporal determinism rules, ai-agent-builder's Chrome-extension globals) stay in the app as overrides.
  • No .prettierignore, paths, include or knip entry lists: they are paths into the app.
  • No Jest preset and no vite.config.js — only the test half of Vite.
  • It never relaxes a rule silently. If an app was looser than the preset, the difference shows up as lint findings, not as a hidden override.