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-mk-cms

v0.1.0

Published

Scaffold a production-ready React CMS for a specific data provider (REST, GraphQL or Supabase).

Readme

create-mk-cms: the project generator

Generates a complete CMS for one data provider from the template/ folder next to this one. The result is not a copy of the template with switches: it contains only the selected provider's code, dependencies, scripts, env, docs, CI and tests, and passes every quality gate on its own.

pnpm create mk-cms my-cms --provider graphql
# or: pnpm dlx create-mk-cms my-cms --provider supabase

Usage

mk-cms <directory> [options]

  -p, --provider <name>        rest | graphql | supabase
      --name <text>            display name shown in the UI (default: derived from the directory)
      --auth <bearer|cookie>   auth strategy (rest and graphql only; default bearer)
      --api-url <url|path>     REST base URL            (rest only,     default /api)
      --graphql-url <url|path> GraphQL endpoint         (graphql only,  default /graphql)
      --supabase-url <url>     Supabase project URL     (supabase only)
      --supabase-anon-key <k>  Supabase anon key        (supabase only; public by design)
      --install / --no-install install dependencies with pnpm   (default: install)
      --git / --no-git         run `git init`                   (default: init)
  -y, --yes                    never prompt; everything must come from flags
      --dry-run                list the files that would be created, write nothing

In a terminal, anything you omit is prompted for (directory, provider, display name, auth strategy, endpoints, install, git). Without a TTY, or with --yes, <directory> and --provider are required.

Safety: it refuses to write into a non-empty directory (a directory containing only .git is fine), validates every value that ends up in generated files (no quotes, $, backticks or angle brackets in the display name; https for Supabase; http(s) or absolute paths for API URLs), rejects flags that do not apply to the chosen provider, and removes a directory it created if generation fails. Requires Node 24+.

What each provider gets

| | rest | graphql | supabase | | --------------------------------------- | ---------------- | -------------------- | ----------------------------- | | Provider code | providers/rest | providers/graphql | providers/supabase | | Shared HTTP transport + session manager | yes | yes | no (the SDK owns the session) | | Bearer / cookie auth config | yes | yes | no | | GraphQL schema, documents, codegen | no | yes (pnpm codegen) | no | | Reference SQL migration + RLS | no | no | yes (supabase/) | | Verified by the repo's E2E suite | yes | yes | no (needs a live project) | | Docker/CSP | API origin | API origin | adds *.supabase.co |

Every project keeps the full feature-first architecture: features with their own models, ports, routes and translations, shared lib, i18n (en/ne/ar with RTL), theme, RBAC, error handling, test utilities, Oxlint + Prettier, Docker, CI, and the architecture test that forbids UI from importing a provider. Adding another provider later is documented in adding-a-provider.md.

pnpm-lock.yaml is intentionally not shipped (a lockfile for all providers would not match a pruned package.json). The installer generates one; commit it. With --no-install run pnpm install yourself.

How it works

template/ is the single source of truth. scripts/snapshot-template.ts copies it into cli/bundled-template/ (what gets published; npm-hostile dotfiles are stored as _gitignore/_npmrc). At run time the CLI applies, per file:

  1. Removal of provider-owned paths (src/manifest.ts), e.g. other providers' folders and src/data/http for SDK-managed providers.
  2. Markers in source files (below).
  3. JSON edits for package.json, tsconfig*.json, .oxlintrc.json (JSON has no comments): drops other providers' dependencies, scripts and include/ignore entries.
  4. Substitutions: package name, display name (title, i18n appName, env, Docker), auth strategy and endpoints.
  5. Prettier on every edited file, so pnpm format:check passes.
  6. A generated README.md.

Marker grammar

Markers are comments, so the template stays valid, lintable, testable code.

// #region provider:rest,graphql   keep the block only for the listed providers
// #endregion                      (`!name` = all except name, `*` = all)
// #region template-only           block that never reaches a generated project
foo(); // @provider:supabase       keep this single line only for the listed providers
mode = "rest"; // @provider-value   replace the provider name on the line with the target
[rest, graphql] // @provider-list   replace the [..] list on the line with [target]
// @provider-value-next            same as @provider-value, for the next line

Comment styles //, # and <!-- --> are supported. In Markdown, fenced code blocks are not processed, and conditional table rows are not possible (use lists). Where two providers need different code, write keyed strategies (see e2e/fixtures/backend-protocol.ts for the same idea) so the file is valid both here and after stripping.

Keeping the template and the generator honest

You never edit a copy of the template; you edit the template, and the generator follows. Three layers stop drift:

  • src/validate.ts scans each generated tree: no leftover markers, no mention of other providers (or of a mock backend / Playwright, which never ship in a project), all Markdown links and backticked src/… paths resolve, no foreign lockfiles.
  • test/*.test.ts (pnpm test): the marker engine, generation for all three providers, file/dependency/script/tsconfig/env assertions, and the CLI's exit codes and safety checks.
  • pnpm verify (CI runs it per provider): really generates each project, installs it, and runs typecheck, lint, format:check, test, build, GraphQL codegen stability, and, for REST and GraphQL, the repository's Playwright suite from ../e2e pointed at the generated project (E2E_APP_DIR).
pnpm test                          # fast (generation only, no install)
pnpm verify                        # all providers, full gates
pnpm verify --provider rest        # one provider (add --skip-e2e, --keep)
pnpm build                         # snapshot + compile to dist
node src/index.ts ../tmp-app --provider rest --yes   # run from source (Node 24)

If a template edit breaks a provider, pnpm test (or pnpm verify) names the file. From the repository root the same commands are pnpm cli:test, pnpm cli:verify and pnpm cli:build.

Publishing

pnpm build                              # snapshots ../template into bundled-template and compiles dist
pnpm pack --pack-destination /tmp       # inspect the tarball (dist + bundled-template)

Publish this folder as create-mk-cms (it exposes the mk-cms executable). Users then run pnpm create mk-cms. Rebuild before every release so the snapshot matches the template.

Adding a provider to the generator

  1. Implement the provider in template/ (adding-a-provider.md) with // #region provider:<name> around its registration points (config/data-providers.ts, env.ts, create-repositories.ts, env files, Dockerfile, CI, docs).
  2. src/providers.ts: add the name and its ProviderInfo.
  3. src/manifest.ts: owned paths, dependencies, scripts.
  4. src/readme.ts: quick start for the new provider.
  5. Run pnpm test and pnpm verify --provider <name>.

Limitations

  • Locales are not pruned per project (all three ship; enable/disable with VITE_SUPPORTED_LOCALES).
  • Generated projects ship no mock backend and no browser tests: those live in ../e2e. Supabase has no E2E at all (it needs a seeded live project); unit and component tests run against in-memory repositories.
  • The generated project does not track future template changes; regenerate and diff to adopt them.