22 Commits
Author SHA1 Message Date
jake 99ed11f5de docs: update CLI and registry documentation for clarity and accuracy
- Enhanced descriptions in `AGENTS.md`, `cli.mdx`, and `getting-started.mdx` to provide clearer guidance on module categories and commands.
- Added information about third-party module publishing in `registry.mdx`.
- Adjusted the order of pages in `meta.json` for better navigation.
- Improved warning and info callouts for better user experience.
2026-06-04 15:58:17 -04:00
jakeandGitHub 04a196e4e9 refactor: serve registry and manifest schema from Vercel Blob as canonical origin (#18) 2026-06-04 15:08:36 -04:00
jakeandGitHub ea2d8c45bd refactor: extract @withstanza/schema and @withstanza/utils packages (#16) 2026-05-30 21:47:16 -04:00
jake e89fb63c31 feat: unify registry loading behind a main file, add apply rollback, and add stanza doctor
- **Registry main file.** The CLI now addresses any registry (first-party, third-party, or `STANZA_REGISTRY` override) by the full URL/path to its JSON index file. The `modules/<category>-<id>.json` convention, the in-repo source-tree loader, the directory-based auto-detect, and the inline-template disk fallback are all removed — one loader, no heuristics. `STANZA_REGISTRY` must be the full path/URL to the main file (not a directory); `registries` entries now carry `url` pointing at the main file instead of an `indexUrl`+template. **Breaking** (pre-release, clean break): registry index bumped to `schemaVersion: 2`; every module entry carries a `path` field resolved relative to the main file.
- **Auto-rollback.** `stanza add` (and each module in `stanza init`) now wraps its file writes in a transaction; a mid-apply failure restores touched files and `stanza.json` to their pre-apply state. `reportApplyFailure` updated to say "The change was rolled back" and demotes the `stanza remove` / `git restore` steps to a backstop note.
- **`stanza doctor`.** New read-only command that checks `stanza.json` against the filesystem (tracked files, deps, scripts, env vars, internal packages) and reports drift, exiting non-zero when found.
- Update integration tests to build the first-party registry once into a temp dir and point `STANZA_REGISTRY` at its main file; update the third-party HTTP fixture server to serve `/index.json` as the main file alongside per-module paths.
- Update `AGENTS.md` E2E smoke instructions and `apps/cli/README.md` to reflect the new loader and `doctor` command.
2026-05-30 12:49:11 -04:00
jake 7349b53b82 feat: add api category, improve stanza add failure reporting, and ship npm READMEs
- Add `api` to the category taxonomy (`cardinality: "one"`, `home: package` → `packages/api/`) for a future typed RPC layer; no first-party modules yet — wizard skips it and the web builder hides it while empty
- Replace the raw `throw err` in `cmdAdd` with `reportApplyFailure`: a `RegionConflictError` states plainly that nothing was written; a mid-apply failure points at `stanza remove …` to sweep tracked files and (when a clean baseline was enforced) `git restore . && git clean -fd` to reset the worktree
- Add npm READMEs to `apps/cli` and `packages/create-stanza` covering quick-start, commands, safety flags, registries, and telemetry
- Unwrap hard-wrapped lines in `category-taxonomy.md` changeset and update AGENTS.md to reference the `compile-registry` vp task instead of the old `prebuild` script
2026-05-30 11:35:14 -04:00
jake 981b1a88d6 fix: rename auth-clerk's app-scoped middleware.tsproxy.ts for Next 16
- Rename the template file and update `src`/`dest` in the adapter's file list to match the new `proxy.ts` convention required by Next 16
- Update the example filename in `AGENTS.md` and `authoring.mdx` (`middleware.ts` → `proxy.ts`) so the scope guidance stays accurate
- Refactor `BarList` bar fill to animate `width` instead of `transform: scaleX` so the gradient and rounded cap don't distort; replace diagonal hatch overlay with a solid gradient + inset ring and tighten leading gap to `gap-1`
2026-05-28 13:01:50 -04:00
jake 1e45429ea3 chore: trim AGENTS.md, expand stanza-cli skill docs, and tidy stats page
- Condense `AGENTS.md` by moving CLI-specific guidance into `skills/stanza-cli/SKILL.md` where it is co-located with the skill it describes
- Expand `SKILL.md` with the relocated context so agent runs against the CLI skill have the full picture without loading root-level agent instructions
- Minor cleanup to `stats.tsx` layout/typography
2026-05-27 19:13:03 -04:00
jake cf233f8275 fix: harden remove sweep safety, snapshot codemods on records, and fix package-home cardinality scope
- Refuse to sweep `packages/<dir>/` in two new cases: (1) stray non-Stanza files exist under the dir (user-authored secrets, scratch scripts, etc.), and (2) a still-installed module lists the dir in `consumesPackages` — both append to `manualCleanup` with targeted hints instead of silently destroying user work; `findStrayFiles` and `collectConsumesPackagesProtectors` (parallel `Promise.all` over all installed records) implement the checks
- Snapshot `codemods` onto each `StanzaModuleRecord` at install time; `remove` drives `revertCodemods` from that snapshot so reversal is correct even when the upstream registry has renamed the adapter or reshuffled codemod ids since install — falls back to the live registry entry only when no snapshot is present
- Fix cardinality scope in `add` for package-home and repo-home categories: pass `undefined` (not `pickedAppId`) to `selectedAll` so the per-project uniqueness check covers all apps; previously a second install targeting a different app could slip past the check only to fail on the next read
- Use composite owner keys (`<id>@<app>`) in `regionsOwnedBy` for app-home installs so two apps installing the same module don't share a region owner and accidentally release each other's claims during remove; bare `<id>` fallback covers pre-snapshot manifests and non-app homes
- Refactor `applyCodemods` / `revertCodemods` to accept `codemods`, `adapterKey`, and `consumesPackages` directly rather than full `Module` + adapter objects; add a comprehensive `codemod-runner.test.ts` covering apply, revert, dry-run, idempotency, and error paths for all built-in codemod types
- Add `packages/registry/src/safe-path.ts` with `safePath` / `isSafePath` guards and tests; use in the codemod runner to reject path-traversal write targets before any disk touch
- Add `set-tsconfig-paths` builtin codemod with tests; harden `add-array-entry-in-call`, `add-jsx-child`, `wrap-root-layout`, and `replace-import` for idempotency and edge cases
- Validate unknown `--app` flags early in `remove` with a targeted error before any registry fetch; replace the `posthog-provider` React component and `posthog.server.ts` in the web app with a unified `analytics.ts` / `api.events.ts` pattern
2026-05-26 22:25:10 -04:00
jake f195505a48 feat: add third-party registry support with @namespace/id module addressing
- Add `packages/registry/src/registry-config.ts` with a Zod schema for the `registries` field in `stanza.json` (string URL prefix or `{ url, indexUrl?, headers?, params? }` object), plus `parseModuleSpec` to split `@ns/id` specs and `expandEnv` to substitute `${VAR}` tokens in header values (dropping the header silently when the env var is unset)
- Replace `loadRegistry` with `loadRegistries(manifest)` in `registry-loader.ts`; the loader reads `registries` from `stanza.json`, builds a per-namespace fetch client with auth headers, and routes module loads to the correct HTTP endpoint — `@stanza` remains the implicit default namespace backed by the existing registry URL
- Update `add`, `remove`, `search`, and `list` commands to accept `[@<namespace>/]<id>` syntax; `namespace` is recorded alongside each module entry in `stanza.json` at install time so `remove` knows which registry to refetch from
- Enforce that codemods are catalog-only: third-party modules may reference first-party codemod IDs but cannot introduce new ones; catalog ID validation runs before any writes so unknown IDs are caught on `--dry-run` too
- Add a full third-party registry test suite in `commands.test.ts` using a stub `node:http` server: covers install + manifest recording, unknown-namespace rejection, remove round-trip (asserts correct namespace URL is hit), `${ENV_VAR}` header expansion, and codemod-catalog enforcement
- Export `DEFAULT_NAMESPACE` and `parseModuleSpec` from `@stanza/registry`; telemetry `cli_module` events now include a `namespace` field so first- vs. third-party installs can be distinguished in PostHog
- Add `apps/web/content/docs/authoring.mdx` covering the full module-authoring reference (schema fields, templates, adapters, codemods, third-party registry config)
2026-05-26 20:12:01 -04:00
jake dd806479d8 feat: add auto-generated project README with checksum-based edit detection and app install-fields overlay
- Add `synthesizeReadme(resolved, ctx)` to `@stanza/registry`: generates a Markdown README from the assembled module selection using each module's `readme` / `description` copy; exported alongside new `Resolved` / `ResolvedEntry` types that capture the module + adapter pair after resolution
- Add `apps/cli/src/lib/readme.ts` with `writeFreshReadme` (used by `init` into a guaranteed-empty dir), `regenerateReadmeIfUnmodified` (used by `add`/`remove` to skip user-edited files), and `readmeChecksum` / `userModifiedReadme` helpers that compare SHA-256 against a new `readmeChecksum` field on `StanzaManifest`; a missing stored checksum with a present file is treated as user-owned (conservative, covers legacy projects)
- Wire README generation into all three commands: `init` calls `writeFreshReadme` after all modules apply and records the checksum; `add` and `remove` call `regenerateReadmeIfUnmodified` post-mutation and warn when the file has been edited; both update `stanza.json` with the new checksum on write
- Add `app` install-fields overlay in `codemod-runner.ts`: a per-module `installFields.app` bucket routes `dependencies`, `devDependencies`, and `scripts` into each consuming app's `package.json` rather than the workspace root or `packages/ui`; use case is package-home modules whose app-scoped shims import npm packages that belong in the app (e.g. `next-themes` for `ui-shadcn-*`); claims are recorded under `app.dependencies.<name>` region keys so removal can reverse them
- Fix `remove.ts` region handling: strip the `app.` prefix before dispatching `dependencies.*` / `devDependencies.*` / `scripts.*` removals so `app`-overlay claims are reversed correctly
- Add `pmRun(pm, script)` helper to `@stanza/registry` and use it in the `init` outro so the suggested dev command respects the project's package manager (e.g. `npm run dev` vs `pnpm dev`)
- Update `ui-shadcn-base` and `ui-shadcn-radix` module definitions to use the new `app` install-fields overlay for app-scoped peer deps; expand `package-json.test.ts`, `synthesize.test.ts`, and `template.test.ts` with coverage for the new paths
2026-05-25 16:23:00 -04:00
jake 678b5bc1af feat: add ui-shadcn-base, ui-shadcn-radix, and ui-tailwind modules; rename styling category to ui
- 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
2026-05-25 15:26:08 -04:00
jake 3304abbe98 feat: add payments-polar module, consolidate registry build into packages/registry, and generalize plugin codemods
- Add `payments-polar`: `@polar-sh/sdk` + framework-native checkout/webhook route handlers for Next.js and TanStack Start; Better Auth bridge variant ships `@polar-sh/better-auth` and wires the plugin into `auth.ts` when `auth: better-auth` is selected; light/dark logos inlined from svgl
- Consolidate the registry build: delete `scripts/registry-build.ts` and move the emit logic into `packages/registry/src/build.ts`, which now accepts an optional positional output-base arg (defaults to `dist/`) and writes `{base}/registry/{index,modules/*}.json` + `{base}/schema.json` directly; `prepare-registry.sh` is reduced to a single `jiti packages/registry/src/build.ts apps/web/public` invocation; CI/release workflows drop the Bun setup + `registry:build` steps since the build now runs inline at web-app prebuild time
- Replace `add-vite-plugin` codemod with the more general `add-plugin-to-call` (targets any `CallExpression` by callee + arg position, not just `vite.config` `plugins` arrays); add `add-package-dep` builtin for imperatively injecting deps into a `package.json` AST node; both are fully tested and registered in the builtins index
- Fix `init` adapter resolution order: precompute a `fullPending` map from all peer-category picks before the apply loop so `resolveAdapter` sees the complete peer set regardless of `categoryOrder` traversal sequence; export `PEER_CATEGORIES` from `@stanza/registry` to support this
2026-05-25 13:19:06 -04:00
jake be001b0037 feat: add multi-app support with per-app module targeting and app-aware manifest schema
- Introduce `AppSpec` (`{ id, dir, kind }`) and `AppKind = "web" | "native"` types; `stanza.json` now declares `apps: AppSpec[]` alongside modules, and `stanza init` scaffolds a default web app via `defaultWebApp()`
- Add optional `apps?: string[]` to `StanzaModuleRecord` to encode which apps a record targets; `home: app` modules require it, `home: package` modules use it to scope workspace deps (omitting means all apps), `home: repo` modules forbid it
- Make cardinality enforcement app-scoped for `home: app` categories: `selectedOne(m, cat, appId?)` and `selectedAll(m, cat, appId?)` now filter by app, and `add`/`remove` thread a `targetApp` through the runner so per-app single-choice rejection works correctly
- Extend the template render context with an `app: { id, dir, kind }` binding (plus the legacy `project.appDir` alias) re-bound per target app; the codemod runner fans out template/codemod/dep application once per consuming app in a loop
- Update `synthesizePackageJsons`, `synthesizeTemplates`, `buildRenderContext`, and related web-preview helpers to accept an `apps` array and produce per-app output
- Update `package-json.ts` to strip workspace deps from all apps' `package.json` on remove and to inject them into every consuming app on install
- Expand `manifest.test.ts` and `template.test.ts` with multi-app fixture coverage; add `"use client"` directive to codemod test files to satisfy the RSC boundary
- Refresh `AGENTS.md`, `SKILL.md`, and all affected docs (`concepts.mdx`, `registry.mdx`, `cli.mdx`, `getting-started.mdx`, `agents.mdx`) to document the new apps schema and routing semantics
2026-05-23 22:26:09 -04:00
jake e6709b24f7 fix: capitalize "Stanza" consistently across docs, code, and templates 2026-05-23 21:40:15 -04:00
jake 8c5433aa3c feat: move template substitution into @stanza/registry and switch to dotted Mustache paths
- Promote `renderTemplate` and `buildRenderContext` from `@stanza/codemods` into `@stanza/registry` alongside `synthesizeManifest`/`synthesizeEnvExample`/`synthesizePackageJsons`; add a new `synthesizeTemplates` export that returns the fully-substituted file list for a resolved selection so the web preview and the CLI apply path share identical logic
- Change the template DSL to dotted paths: `{{project.name}}` (was `{{projectName}}`), `{{project.appDir}}` (was `{{appDir}}`), `{{package.name}}` (was `{{packageName}}`), and `{{packages.<dir>.name}}` (was `{{<dir>PackageName}}`, e.g. `{{packages.db.name}}`); add a `TemplateContext` type exported from `@stanza/registry`
- Migrate all first-party modules (`auth-better-auth`, `auth-clerk`) to the new dotted syntax; fixes the web builder preview regression where tokens like `{{dbPackageName}}` appeared unsubstituted
- Update AGENTS.md docs and CLI `codemod-runner.ts` to reflect the new context shape and import locations
2026-05-22 19:58:09 -04:00
jake 78f8e44721 chore: migrate to vite+ 2026-05-22 18:37:24 -04:00
jake 9bf80ce2e8 docs: expand README and documentation site with concepts, getting-started, and CLI reference pages
- Add `concepts.mdx` covering categories, cardinality, home, vendoring, peers/adapters, manifest, regions, and the open registry model
- Flesh out `getting-started.mdx` with prerequisites, install/run steps, package-manager variants, inspect/remove commands, and a non-interactive `--yes` example
- Rewrite `cli-reference.mdx` with per-verb sections, global flags, environment variables, and dependency-versioning semantics
- Expand `README.md` with a "Why Stanza?" section, quick-start snippet, docs link, and updated module list; swap `pnpm create` example for `npm init`
- Add `concepts` to `meta.json` nav order
2026-05-22 16:03:15 -04:00
jake 71f4c9d89b refactor: unify module taxonomy into a single Category concept with cardinality and home
- Replace the `slot` / `add-on` discriminated-union split with one `Category` shape carrying two orthogonal fields: `cardinality` (`"one"` for single-choice, `"many"` for coexisting) and `home` (`"app"` / `"repo"` / `"package"`) — the old `packageDir` + `repoScoped` pair is dropped
- `Module` is no longer a discriminated union; it carries a single `category` field referencing a `Category` id; `KNOWN_SLOTS`, `KNOWN_ADDONS`, `ADDON_CATEGORIES`, and all related helpers are replaced by a single `CATEGORIES` array and derived `categoryHome` / `categoryLabel` / `PACKAGE_DIRS` lookups
- Manifest schema bumped to version `0.2` — `modules` is now one record keyed by category holding arrays; `cardinality: "one"` categories are enforced to ≤ 1 entry at install time; no migration (stanza is pre-1.0 and unpublished)
- Peer/constraint logic is now emergent from cardinality: the resolver treats only `cardinality: "one"` categories as peers, so `testing` (many) can never accidentally become a peer; install routing is a single `categoryHome` lookup shared by the CLI runner, codemod runner, and web preview
- Update all CLI commands (`add`, `remove`, `init`, `list`, `search`), the wizard, `codemod-runner`, `registry-loader`, all web builder/detail/search components, server functions, OG route, sitemap, analytics, and selection logic to use the new category API
- Update all first-party `module.ts` files, `registry-build.ts`, tests, and docs (`AGENTS.md`, `REGISTRY.md`, `SKILL.md`) to reflect the unified taxonomy
2026-05-21 23:03:02 -04:00
jake c454f30798 feat: add optimistic slot/addon selection, warm Shiki on load, and fix file-tree expand replay
- Wrap `setSelection` and `toggleAddon` in `startTransition` + `useOptimistic` so card borders and checkmarks flip instantly on click; the preview pane continues to wait on committed loader data (server-rendered Shiki HTML) and shows its own spinner for that round-trip
- Fire-and-forget `getHighlighter()` during the initial `getBuilderState` call so the Shiki singleton is warm before the first slot toggle, eliminating cold-start latency on the first preview render
- Fix `initialExpandedPaths` replay in `FilePreview`: filter the expanded-dir set to only directories whose entire ancestor chain is also expanded, preventing a collapsed parent from being re-opened when its still-flagged descendant is replayed
- Hoist the loading overlay outside the empty/non-empty branch so it also covers the initial `filePaths === []` → content transition, where `filePaths` is still stale while the loader is in flight
2026-05-21 22:22:03 -04:00
jake 890673d334 fix: polish docs sidebar mobile disclosure, search result layout, and dropdown close behavior
- Restyle the mobile docs `<details>` disclosure with a bordered summary, animated `IconChevronRight` chevron, and a top-border separator below the open panel instead of a bottom-border above it
- Tighten `NavLink` padding (`py-1`) and add `rounded` so the active highlight matches the app's pill style; reduce separator top-padding from `pt-4` to `pt-3`
- Add `closeOnClick` to every `DropdownMenuRadioItem` in `ModeToggle` and `PackageManagerSelect` so the menu closes after a selection
- Strip the `moduleGroup/id` monospace trailing span from `SearchResult` rows to reduce visual noise
- Remove the per-item inline padding override on Shiki `.line` elements (`pl-0! pr-0!`) so code blocks no longer get double inset
- Reduce docs article top padding on mobile (`pt-2`) while keeping `md:pt-8` on wider viewports
2026-05-21 19:51:10 -04:00
jake d1498a9ff6 docs: add stanza-cli installable agent skill and reference it from AGENTS.md
- Add `skills/stanza-cli/SKILL.md` — a self-contained agent skill covering the published CLI surface: runtime contract, non-interactive `init`/`add`/`remove`/`list`/`search` usage, slot vs. add-on semantics, safety flags (`--dry-run`, `--dangerously-allow-dirty`, `STANZA_REGISTRY`), error handling, and agent rules; intended for agents that don't have access to this source repo
- Add `skills/stanza-cli/agents/openai.yaml` with display name, short description, and default prompt for OpenAI agent tooling
- Update `AGENTS.md` with a "Distributed Skill" section noting that `skills/stanza-cli/SKILL.md` must be kept in sync whenever CLI flags, command behaviour, slot/add-on names, or published package names change
2026-05-21 17:39:52 -04:00
jake 71b55d8bc8 docs: rename CLAUDE.md to AGENTS.md for broader agent compatibility 2026-05-21 17:27:07 -04:00