From 678b5bc1af7d8e2f980d20abe8286b7ba3c31513 Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Mon, 25 May 2026 15:26:08 -0400 Subject: [PATCH] feat: add ui-shadcn-base, ui-shadcn-radix, and ui-tailwind modules; rename `styling` category to `ui` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename `styling` → `ui` across the entire codebase (CATEGORIES array, docs, AGENTS.md, CLI tests, resolver, template tests, codemod runner); `ui` is `home: package` so shadcn installs into `packages/ui/` as a workspace dep rather than wiring directly into the app shell - Add `ui-shadcn-base` (Tailwind v4 / CSS-first, no Radix peer) and `ui-shadcn-radix` (Tailwind v4 + Radix primitives) with full per-framework template sets for Next.js and TanStack Start: `components.json`, `globals.css`, `postcss.config.mjs`, `theme-provider.tsx`, shared `Button` + `utils.ts`; light/dark logos inlined from svgl - Rename `styling-tailwind` → `ui-tailwind` to match the new category id; update its module definition to `category: "ui"` and `home: package` - Add four new codemod builtins with tests: `add-array-entry-in-call` (inserts an element into a named array argument of any `CallExpression`), `replace-import` (rewrites a specifier in an existing import declaration), `set-html-attributes` (sets attributes on an HTML/JSX element by tag name or selector), `set-tsconfig-paths` (merges `compilerOptions` entries into a `tsconfig.json` AST node); register all four in the builtins index and export from `@stanza/codemods` - Add `wrap-root-layout` builtin tests - Update registry.mdx, concepts.mdx, cli.mdx, getting-started.mdx, agents.mdx, index.mdx, AGENTS.md, README.md, TODO.md, and SKILL.md to reflect the category rename and new modules --- AGENTS.md | 12 +- README.md | 4 +- TODO.md | 8 +- apps/cli/src/commands/commands.test.ts | 6 +- apps/cli/src/lib/codemod-runner.ts | 57 +-- apps/cli/src/run.ts | 4 +- apps/web/content/docs/agents.mdx | 56 +-- apps/web/content/docs/cli.mdx | 56 +-- apps/web/content/docs/concepts.mdx | 87 +--- apps/web/content/docs/getting-started.mdx | 38 +- apps/web/content/docs/index.mdx | 24 +- apps/web/content/docs/registry.mdx | 89 ++-- .../builtins/add-array-entry-in-call.test.ts | 167 +++++++ .../src/builtins/add-array-entry-in-call.ts | 416 ++++++++++++++++++ packages/codemods/src/builtins/index.ts | 24 +- .../src/builtins/replace-import.test.ts | 127 ++++++ .../codemods/src/builtins/replace-import.ts | 103 +++++ .../src/builtins/set-html-attributes.test.ts | 131 ++++++ .../src/builtins/set-html-attributes.ts | 200 +++++++++ .../src/builtins/set-tsconfig-paths.test.ts | 111 +++++ .../src/builtins/set-tsconfig-paths.ts | 157 +++++++ .../src/builtins/wrap-root-layout.test.ts | 226 ++++++++++ packages/codemods/src/index.ts | 2 + packages/registry/src/module.ts | 8 +- packages/registry/src/package-json.ts | 28 +- packages/registry/src/resolver.test.ts | 2 +- packages/registry/src/resolver.ts | 2 +- packages/registry/src/template.test.ts | 6 +- pnpm-lock.yaml | 115 ++++- registry/modules/ui-shadcn-base/logo-dark.svg | 1 + .../modules/ui-shadcn-base/logo-light.svg | 1 + registry/modules/ui-shadcn-base/module.ts | 230 ++++++++++ .../package.json | 2 +- .../templates/next/app/components.json | 23 + .../next/app/components/theme-provider.tsx | 71 +++ .../templates/next/app/postcss.config.mjs | 1 + .../templates/next/package/postcss.config.mjs | 6 + .../next/package/src/styles/globals.css | 129 ++++++ .../templates/shared/package/components.json | 23 + .../shared/package/src/components/button.tsx | 58 +++ .../templates/shared/package/src/lib/utils.ts | 6 + .../tanstack-start/app/components.json | 23 + .../app/components/theme-provider.tsx | 91 ++++ .../package/src/styles/globals.css | 130 ++++++ .../tsconfig.json | 0 .../modules/ui-shadcn-radix/logo-dark.svg | 1 + .../modules/ui-shadcn-radix/logo-light.svg | 1 + registry/modules/ui-shadcn-radix/module.ts | 230 ++++++++++ registry/modules/ui-shadcn-radix/package.json | 12 + .../templates/next/app/components.json | 23 + .../next/app/components/theme-provider.tsx | 71 +++ .../templates/next/app/postcss.config.mjs | 1 + .../templates/next/package/postcss.config.mjs | 6 + .../next/package/src/styles/globals.css | 129 ++++++ .../templates/shared/package/components.json | 23 + .../shared/package/src/components/button.tsx | 67 +++ .../templates/shared/package/src/lib/utils.ts | 6 + .../tanstack-start/app/components.json | 23 + .../app/components/theme-provider.tsx | 91 ++++ .../package/src/styles/globals.css | 130 ++++++ .../modules/ui-shadcn-radix/tsconfig.json | 5 + .../logo.svg | 0 .../module.ts | 18 +- registry/modules/ui-tailwind/package.json | 12 + .../templates/next/postcss.config.mjs | 1 + .../templates/package}/postcss.config.mjs | 0 registry/modules/ui-tailwind/tsconfig.json | 5 + skills/stanza-cli/SKILL.md | 6 +- 68 files changed, 3610 insertions(+), 312 deletions(-) create mode 100644 packages/codemods/src/builtins/add-array-entry-in-call.test.ts create mode 100644 packages/codemods/src/builtins/add-array-entry-in-call.ts create mode 100644 packages/codemods/src/builtins/replace-import.test.ts create mode 100644 packages/codemods/src/builtins/replace-import.ts create mode 100644 packages/codemods/src/builtins/set-html-attributes.test.ts create mode 100644 packages/codemods/src/builtins/set-html-attributes.ts create mode 100644 packages/codemods/src/builtins/set-tsconfig-paths.test.ts create mode 100644 packages/codemods/src/builtins/set-tsconfig-paths.ts create mode 100644 packages/codemods/src/builtins/wrap-root-layout.test.ts create mode 100644 registry/modules/ui-shadcn-base/logo-dark.svg create mode 100644 registry/modules/ui-shadcn-base/logo-light.svg create mode 100644 registry/modules/ui-shadcn-base/module.ts rename registry/modules/{styling-tailwind => ui-shadcn-base}/package.json (82%) create mode 100644 registry/modules/ui-shadcn-base/templates/next/app/components.json create mode 100644 registry/modules/ui-shadcn-base/templates/next/app/components/theme-provider.tsx create mode 100644 registry/modules/ui-shadcn-base/templates/next/app/postcss.config.mjs create mode 100644 registry/modules/ui-shadcn-base/templates/next/package/postcss.config.mjs create mode 100644 registry/modules/ui-shadcn-base/templates/next/package/src/styles/globals.css create mode 100644 registry/modules/ui-shadcn-base/templates/shared/package/components.json create mode 100644 registry/modules/ui-shadcn-base/templates/shared/package/src/components/button.tsx create mode 100644 registry/modules/ui-shadcn-base/templates/shared/package/src/lib/utils.ts create mode 100644 registry/modules/ui-shadcn-base/templates/tanstack-start/app/components.json create mode 100644 registry/modules/ui-shadcn-base/templates/tanstack-start/app/components/theme-provider.tsx create mode 100644 registry/modules/ui-shadcn-base/templates/tanstack-start/package/src/styles/globals.css rename registry/modules/{styling-tailwind => ui-shadcn-base}/tsconfig.json (100%) create mode 100644 registry/modules/ui-shadcn-radix/logo-dark.svg create mode 100644 registry/modules/ui-shadcn-radix/logo-light.svg create mode 100644 registry/modules/ui-shadcn-radix/module.ts create mode 100644 registry/modules/ui-shadcn-radix/package.json create mode 100644 registry/modules/ui-shadcn-radix/templates/next/app/components.json create mode 100644 registry/modules/ui-shadcn-radix/templates/next/app/components/theme-provider.tsx create mode 100644 registry/modules/ui-shadcn-radix/templates/next/app/postcss.config.mjs create mode 100644 registry/modules/ui-shadcn-radix/templates/next/package/postcss.config.mjs create mode 100644 registry/modules/ui-shadcn-radix/templates/next/package/src/styles/globals.css create mode 100644 registry/modules/ui-shadcn-radix/templates/shared/package/components.json create mode 100644 registry/modules/ui-shadcn-radix/templates/shared/package/src/components/button.tsx create mode 100644 registry/modules/ui-shadcn-radix/templates/shared/package/src/lib/utils.ts create mode 100644 registry/modules/ui-shadcn-radix/templates/tanstack-start/app/components.json create mode 100644 registry/modules/ui-shadcn-radix/templates/tanstack-start/app/components/theme-provider.tsx create mode 100644 registry/modules/ui-shadcn-radix/templates/tanstack-start/package/src/styles/globals.css create mode 100644 registry/modules/ui-shadcn-radix/tsconfig.json rename registry/modules/{styling-tailwind => ui-tailwind}/logo.svg (100%) rename registry/modules/{styling-tailwind => ui-tailwind}/module.ts (80%) create mode 100644 registry/modules/ui-tailwind/package.json create mode 100644 registry/modules/ui-tailwind/templates/next/postcss.config.mjs rename registry/modules/{styling-tailwind/templates/next => ui-tailwind/templates/package}/postcss.config.mjs (100%) create mode 100644 registry/modules/ui-tailwind/tsconfig.json diff --git a/AGENTS.md b/AGENTS.md index aa19234..6b80ce1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Stanza -Shadcn-style CLI for assembling modular full-stack TS monorepos. Currently ships `init`, `add`, `remove`, `list`, `search` against these **categories**: `framework`, `styling`, `db`, `orm`, `auth`, `tooling`, `testing`. `swap` + `update` verbs and more categories (api, ai, ui, payments, deploy, email, monorepo) are planned — the manifest already reserves the fields they'll need (`modules[category][].version`, `regions`). See the [module registry](apps/web/content/docs/registry.mdx) for the module roadmap and [TODO.md](TODO.md) for active work. +Shadcn-style CLI for assembling modular full-stack TS monorepos. Currently ships `init`, `add`, `remove`, `list`, `search` against these **categories**: `framework`, `ui`, `db`, `orm`, `auth`, `tooling`, `testing`. `swap` + `update` verbs and more categories are planned — the manifest already reserves the fields they'll need (`modules[category][].version`, `regions`). See the [module registry](apps/web/content/docs/registry.mdx) for the module roadmap and [TODO.md](TODO.md) for active work. Three things differentiate Stanza from other scaffolders: @@ -19,7 +19,7 @@ Three things differentiate Stanza from other scaffolders: A generated project has one or more **apps** declared in `stanza.json` as `apps: [{ id, dir, kind }]` (e.g. `{ id: "web", dir: "apps/web", kind: "web" }`). `AppKind = "web" | "native"` is a closed enum, and framework modules declare an `appKind` so the runner can validate that the framework matches its target app. `stanza init` scaffolds a single web app today (`defaultWebApp()`); multi-app init is a planned follow-up, but schema and runtime are already multi-app-shaped — `applyModule` threads a `targetApps: AppSpec[]` per call, and the web builder's `synthesize*` functions all take an `apps` array. -In a **generated project**, a module's output lands per its category's `home` (in the canonical [`CATEGORIES`](packages/registry/src/module.ts) array): `auth`/`db`/`orm` (`home: package`) install into an internal workspace package at `packages//` (named `@/`, consumed via `workspace:*` by every consuming app; `db` + `orm` share `packages/db/`); `framework`/`styling`/`testing` (`home: app`) wire the chosen app's shell; `tooling` (`home: repo`) writes config at the repo root + scripts in the root `package.json`. The app a record targets is encoded as `apps: ["", …]` on `StanzaModuleRecord` — **required** for `home: app`, **optional** for `home: package` (omitted means "ship app-scoped shims into every app"; an explicit list restricts), and **forbidden** for `home: repo`. The app `id` doubles as the workspace package suffix: `@/` (so `id: "web"` → `@acme/web`, regardless of `dir`). `categoryHome(id)`, `PACKAGE_DIRS`, and `categoryLabel(id)` are all derived from the `CATEGORIES` array. +In a **generated project**, a module's output lands per its category's `home` (in the canonical [`CATEGORIES`](packages/registry/src/module.ts) array): `auth`/`db`/`orm`/`ui` (`home: package`) install into an internal workspace package at `packages//` (named `@/`, consumed via `workspace:*` by every consuming app; `db` + `orm` share `packages/db/`); `framework`/`testing` (`home: app`) wire the chosen app's shell; `tooling` (`home: repo`) writes config at the repo root + scripts in the root `package.json`. The app a record targets is encoded as `apps: ["", …]` on `StanzaModuleRecord` — **required** for `home: app`, **optional** for `home: package` (omitted means "ship app-scoped shims into every app"; an explicit list restricts), and **forbidden** for `home: repo`. The app `id` doubles as the workspace package suffix: `@/` (so `id: "web"` → `@acme/web`, regardless of `dir`). `categoryHome(id)`, `PACKAGE_DIRS`, and `categoryLabel(id)` are all derived from the `CATEGORIES` array. The repo runs on the **Vite+ toolchain** (`vp`) — one CLI for dev/build/test/lint/fmt/check/pack, all configured by the root [`vite.config.ts`](vite.config.ts) (`test`/`lint`/`fmt`/`staged` blocks). There is **no** `turbo.json`, `.oxlintrc.json`, `.oxfmtrc.json`, or per-package `vitest.config.ts` — that config now lives in `vite.config.ts`. `vp run