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

@modyo/widget-validator

v0.1.4

Published

Validator for Modyo widgets built with Dynamic UI

Readme

@modyo/widget-validator

npm version License: Modyo

Validator for Modyo widgets built with Dynamic UI. Ships both as a CLI and as a programmatic library.

Installation

npm install --save-dev @modyo/widget-validator

Or run it without installing:

npx @modyo/widget-validator ./path/to/widget

CLI usage

modyo-widget-validator ./path/to/widget

Exit code is 0 when no errors are reported, 1 otherwise. Warnings do not affect the exit code.

Sample output:

╔══════════════════════════════════════╗
║        Modyo Widget Validator        ║
║                v0.1.0                ║
╚══════════════════════════════════════╝

🔍 Validating widget at: /path/to/widget

═══════════════════════════════════════
         VALIDATION REPORT
═══════════════════════════════════════

Widget: /path/to/widget
Score: 100%
Passed: 110/110

✅ PASSED - Widget meets all requirements

✅ All checks passed!

Programmatic usage

import { validateWidgetPath } from "@modyo/widget-validator";

const report = await validateWidgetPath("./path/to/widget");

if (!report.passing) {
  for (const issue of report.errors) {
    console.error(`[${issue.category}] ${issue.message}`);
    if (issue.file) console.error(`  → ${issue.file}`);
    if (issue.suggestion) console.error(`  💡 ${issue.suggestion}`);
  }
}

validateWidgetPath(projectPath, options?)

Validates a widget at the given filesystem path. Returns a Promise<ValidationReport>.

validateWidget(files, options?)

Validates a widget represented as an array of VirtualFile. Useful when the widget exists in memory rather than on disk. See "Known limitations" below.

ValidateOptions

interface ValidateOptions {
  /** Categories to skip (e.g. ["Accessibility"]). */
  excludeCategories?: string[];
}

Score is recalculated after exclusion, so skipped categories don't bias the result.

ValidationReport

interface ValidationReport {
  widgetPath: string;
  score: number;           // 0–100
  passing: boolean;        // true iff errors.length === 0
  totalChecks: number;
  passed: number;
  errors: Issue[];
  warnings: Issue[];
  timestamp: string;       // ISO 8601
  version: string;         // version of @modyo/widget-validator that produced the report
}

interface Issue {
  severity: "error" | "warning";
  category: string;
  rule: string;
  message: string;
  file?: string;           // path relative to widget root, when applicable
  line?: number;
  suggestion?: string;
}

Rules

The validator runs 20 rules organized by category. A rule may produce multiple checks (e.g. "Required Files" checks ~17 files individually).

| Category | What it checks | |---|---| | Folder Structure | The widget has the expected directory layout (src/, src/components/, etc.) | | Required Files | Files like package.json, vite.config.ts, src/main.tsx exist | | Legacy Files | No files from the previous stack (CRA, legacy configs) remain | | Naming Conventions | Repositories are PascalCaseRepository.ts, components are PascalCase.tsx, hooks are useX.ts | | Dependencies | Required dependencies are present, forbidden ones absent, peer deps meet minimum versions | | TypeScript | tsconfig.json has strict: true, JSX configured, target ≥ ES2020 | | Vite Config | vite.config.ts includes React plugin and Vitest config | | TanStack Query | QueryProvider is set up correctly | | Zustand Store | useUIStore exists and doesn't hold server-fetched data | | i18n | src/locales/en.json and src/locales/es.json exist and are non-empty | | Testing | A tests/ folder, setup file, and at least one test exist; hooks have tests; tests follow folder conventions | | Error Handling | src/utils/errorHandler.ts exists and exports the expected helpers | | Repository Pattern | At least one repository file with async methods exists | | Portal System | DContextProvider is set up in src/main.tsx; modals/offcanvas register in availablePortals | | UI Patterns | No container-fluid className is used (use container) | | Project Structure | Only README.md lives at the project root (no scattered .md files) | | Data States | TSX files using query hooks check isLoading/isPending, isError, and empty states | | Error Boundary | An ErrorBoundary component exists and is used in src/App.tsx | | Accessibility | <DInput> has labels, <DButton> (icon-only) has text/aria-label, <img> has alt |

Known limitations

validateWidget and empty directories (v0.1)

VirtualFile[] cannot represent empty directories. The validator requires several directories to exist (src/hooks, src/types, etc.), and feeding it a VirtualFile[] constructed from a real widget will lose those empty directories during the round-trip, causing false "Missing required folder" errors.

Workaround: include a sentinel file in each empty directory (e.g. <dir>/.gitkeep).

This restriction will be lifted in v0.2 via an in-memory filesystem abstraction.

License

See LICENSE.md for the Modyo license.