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

create-procode

v1.0.0

Published

Scaffold a React + TypeScript + Vite app wired to the four ProCode low-code libraries (core, kendo-widget, vs-template, vs-theme).

Readme

create-procode

Scaffold a React 18 + TypeScript + Vite application wired to the four ProCode low-code libraries — with main.tsx, all five extension points, a working sample screen and the import-boundary ESLint config already in place.

npm create procode@latest myapp
# or
npx create-procode myapp

Usage

# interactive — every question has a default; press Enter to accept it
npm create procode@latest

# name positionally, everything else prompted
npx create-procode myapp

# fully specified, no prompts
npx create-procode myapp --app-code MYAPP --base /myapp --yes

# the same through npm create — options go after `--`
npm create procode@latest myapp -- --app-code MYAPP --base /myapp --yes

Options

| Option | Default | What it sets | |---|---|---| | <name> / --name <name> | procode-app | Project directory and package name | | --app-code <code> | derived from the name | VITE_APPLICATION_CODE, and therefore the getAdapter<CODE> global | | --base <path> | /<name> | Vite base and VITE_HOMEPAGE — kept equal by construction | | --api-url <url> | QA placeholder | VITE_CENTRAL_SERVICE_BASE_URL; a {APP_CODE} placeholder is filled in | | --auth-url <url> | https://localhost:7016/token | VITE_AUTH_URL | | --tool-url <url> | the low-code tool host | VITE_TOOL_BASE_URL | | --env <name> | InDraft | VITE_PROJECT_ENVIROMENT — InDraft or Published | | --pm <pm> | auto-detected | npm | pnpm | yarn | bun | | --no-install | installs | Skip the dependency install | | --no-git | inits | Skip git init | | --no-sample | includes it | Skip the sample module screen (leaves the registries empty but wired) | | --no-lint | includes it | Skip ESLint config and its dev dependencies | | --no-latest | resolves latest | Use the tested library versions in src/deps.mjs instead of the newest published ones | | -y, --yes | — | Take defaults for everything not passed as a flag | | -f, --force | — | Scaffold into a non-empty directory | | -h, --help / -v, --version | — | |

Anything not passed as a flag is asked interactively, with a default already filled in — so you can drive this entirely from flags, entirely from prompts, or any mix. With --yes, or when stdin is not a TTY (CI), nothing is asked.

What you get

myapp/
├── README.md                     quick start, layout, the rules, pinned versions
├── package.json                  the newest ProCode releases + the peers they declare
├── index.html                    root element + favicon link
├── vite.config.ts                base, es2020 target, optimizeDeps
├── tsconfig.json / tsconfig.node.json
├── .env / .env.local.example     every var the core reads, documented
├── .nvmrc                        Node 24
├── .eslintrc.cjs                 the framework's import boundary, at lint time
├── .vscode/extensions.json       recommends the ESLint extension
├── .gitignore
├── public/favicon.svg            served from the base path
└── src/
    ├── main.tsx                  the single integration point — every <Core> prop, typed
    ├── vite-env.d.ts             typed import.meta.env
    ├── constant.ts               APPLICATION_CODE, AuthToken, the three registry enums
    ├── localizationResolver.ts   answers vs-template's date / currency lookups
    ├── icons.ts                  registerIcons map
    ├── routes.ts                 customRoute
    ├── Screens/                  LoaderElement, ErrorElement, PageNotFoundElement
    ├── Utils/                    responseFormatter, fieldErrorMapper, errorMessageMapper,
    │                             customStorages, the shared log sink
    ├── Module/                   (1) slug -> schema      + Sample/Contacts.json
    ├── AdapterProvider/          (2) screenId -> adapter + SampleContacts.ts (seeds the rows)
    ├── Factory/
    │   ├── CustomWidgetFactory.tsx      (3) custom widgets
    │   ├── CustomValidationFactory.tsx  (5) custom validations
    │   ├── CustomRuleEffectFactory.ts   custom rule effects (customRuleEffectProvider)
    │   ├── RuleEffects/readOnlyEffect.ts  CUS_READONLY, used by the sample
    │   ├── Widgets/MyWidget/            a presentation-only widget, composed from library widgets
    │   ├── Widgets/SectionNav/          the "Sections" rail for long forms
    │   ├── Widgets/Notification/        the app's one toast host
    │   ├── Actions/setField.ts          CUS_SET_FIELD — a button reaching MODIFY_MODEL
    │   ├── Actions/myAction.ts          the custom widget's two actions
    │   ├── Actions/sampleContacts.ts    stand-ins for the API-backed standard actions
    │   └── Validations/myValidation.ts
    ├── CustomAction.ts           (4) custom actions, keyed CUS_*
    ├── CustomAuthorizationProvider.ts
    └── assets/styles/index.scss  the five-layer SCSS cascade, in order

The sample screen

One JSON document with no backend, built to show what the stack does declaratively:

| Coordinate | Value | |---|---| | slug | sample → src/Module/index.ts | | schema | src/Module/Sample/Contacts.json | | screenId | sample-contacts | | adapter | SampleContacts → src/AdapterProvider/AdapterFactory.ts |

  • H1 heading and a permission-gated Add contact button (CustomAuthorizationProvider).
  • Three vs-template BLOCK summary tiles bound to the view model.
  • A GRID with sorting, column search, checkbox selection and three bulk actions that open CONFOMATIONALERTBOX with the selection count spliced into the text; the name column is a NAVIGATIONCELL that opens the inline editor. Sort and search travel through the grid's onScreenDataLoad event, the same path LOAD_SCREEN_DATA takes against a server (paging is server-side by design).
  • An editor shown by a ruleInterpreter entry, with TEXTBOX, DROPDOWN (inline options), DATE, SWITCH, TEXTAREA, the custom MY_WIDGET (composed from the library's TextBox and Button), standard validators, MY_VALIDATION, and a conditional Sales region field driven by a second rule.
  • Save validates every editor field through the core's executeValidation seam, upserts the row, refreshes the tiles and opens INFOMATIONALERTBOX.

The rows are seeded by the adapter's defaultViewModel. Five small actions in sampleContacts.ts stand in for DELETE_ASYNC / UPDATE_ASYNC / FORMSUBMIT_CREATE_ASYNC; each header names the standard key that replaces it, and the schema's _readme lists the three swaps. The smoke test derives its registry checks from the schema itself: every widgetType, action key, validation name, rule target, bulk-action target and permission key in the sample is verified against the registries.

Pass --no-sample for empty-but-wired registries instead.

What the generated project encodes

These failure modes are prevented by construction rather than left to memory:

  • The newest ProCode libraries, with matching peers. At scaffold time the CLI asks the npm registry for the latest version of each of the four packages, and writes the React, Kendo, router and axios ranges those versions declare as peers. @progress/kendo-theme-default and kendo-react-labels follow the kendo-react range, and @types/react follows the React major. A library release reaches new apps with no generator update. It uses the registry npx was run with, so a mirror works. If the lookup fails (offline, a timeout), the CLI warns and uses the tested set in src/deps.mjs; --no-latest chooses that set on purpose.
  • React stays on the major the libraries declare. Today that is react ^18.2.0; 19 installs cleanly then fails at runtime.
  • react-redux is never declared. It is bundled inside the core. Declaring it and floating to 9.x gives two Provider contexts, and every screen renders blank with nothing in the console.
  • @progress/kendo-theme-default is included. It is a missing peer declaration, not an optional extra — the widget library's SCSS imports it by name, so omitting it is a hard build failure on the first npm run dev.
  • build.target: es2020. At es2015 the downlevel transform miscompiles a const declaring two rest patterns at once, and Kendo's date picker throws "Cannot destructure 'null' as it is null" in built bundles only.
  • base and VITE_HOMEPAGE are written from one value, so they cannot drift.
  • VITE_APPLICATION_CODE is validated as a JS identifier fragment, because it becomes the getAdapter<CODE> global the core resolves by name.
  • The SCSS import order is fixed and annotated — it is the cascade, and reordering gives "Undefined variable" or silently wrong spacing.
  • main.tsx ordering is annotated as load-bearing, with validateStatus first, and the smoke test asserts it.
  • Every <Core> seam is wired, and type-checked. <Core> accepts any, so a misspelled prop compiles and is silently dropped. main.tsx builds a typed CoreProps object instead, and the smoke test asserts every seam is in it: widget, action, validation and rule-effect providers, authorization, routes, storages, response formatting, 422 field errors, error-message text, the 401 handler, the loader / error / 404 screens and the notification host. The core and widget loggers, registerIcons and registerLocalization are registered before render. Deprecated props are never emitted.
  • Rule effects are injectable. CustomRuleEffectFactory is resolved before the standard effects, so it can add effects or override SHOW / HIDE. The sample uses its CUS_READONLY, and the smoke test checks every effect a schema names is standard or registered.
  • Factories use Map lookups. On a plain object, a key like "constructor" returns an Object.prototype function the core would invoke.
  • The core stylesheet builds on Linux. procode-lowcode-core exports ./styles as src/Assets/…, but ships src/assets/…. A Vite alias points the import at the real path, so CI and Docker builds stop failing with "Can't find stylesheet to import".
  • The localization seam is registered. main.tsx calls vs-template's registerLocalization() with src/localizationResolver.ts before render. It answers every LocalizationKey from one date pattern, including dateFormatSections. Without that key, a date box's placeholder changes to Kendo's long form on focus.
  • The framework's import boundary is enforced at lint time. Custom code is still built from library parts: a control inside a custom widget is the library's TextBox / Dropdown / Button from procode-lowcode-kendo-widget/widgets, never @progress/kendo-react-*; icons go through loadIcon / registerIcons, never a second icon set; navigation is NAVIGATE / MENUNAVIGATE, never window.location; toasts are responseConfig or the one Notification host, never react-toastify elsewhere; react-redux, react-router-dom and procode-*/src/… deep paths are library internals. .eslintrc.cjs refuses any of those. It honours one escape hatch — a // procode-escalation: <key> — L<n> cannot compose this because <limitation> comment — for a control the library genuinely does not wrap, so every exception is greppable. The sample MyWidget is itself composed from library widgets, so the first custom widget a developer copies is a correct one.

Maintenance

Library versions

New apps get the latest ProCode releases automatically, so a library release needs no generator change. src/deps.mjs holds two things that still need care:

  • The tested fallback set: used with --no-latest or when the registry is unreachable. Refresh it after a library release has been verified, then run the smoke test with --install. Current pins: core ^2.5.0, kendo-widget ^2.11.0, vs-template ^2.13.1, vs-theme ^2.6.0 (the latest releases as of 2026-10-12).
  • UNDECLARED_BUT_REQUIRED: packages the libraries need but do not declare as peers, so the lookup cannot find them. Add one here if a release starts needing a new one.

The generated README's version table is rendered from whichever set was used.

Test

npm run smoke                 # scaffold + structural assertions, seconds
node scripts/smoke-test.mjs --install   # also npm install + npm run build
node scripts/smoke-test.mjs --keep      # leave the generated app for inspection

The --install run is the only one that catches a dependency set that resolves on paper but not in practice.

Publishing

npm version patch
npm publish

files in package.json ships bin/, src/ and templates/ — about 50 KB packed.

Requirements

Node 18+ to run the generator. Node 24 recommended for the generated app. Zero runtime dependencies — the CLI uses only Node builtins.