Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
595cf3e
feat(bulma-ui): add ./constants subpath export
allxsmith Sep 15, 2026
790d4e9
feat(eslint-plugin): add @allxsmith/eslint-plugin-bestax
allxsmith Sep 15, 2026
f39e49b
fix(eslint-plugin): make the preset lint, and stop the fixes breaking…
allxsmith Sep 15, 2026
41a4d0b
docs(eslint-plugin): lead the setup with the TypeScript form
allxsmith Sep 16, 2026
018452f
docs: note that the ESLint plugin sends no telemetry
allxsmith Sep 16, 2026
59d1a54
fix(eslint-plugin): make the preset's file glob honest about its parser
allxsmith Sep 17, 2026
4853aa5
fix(eslint-plugin): stop three autofixes changing what renders
allxsmith Sep 17, 2026
fc740d1
fix(eslint-plugin): judge only the JSX attribute that wins
allxsmith Sep 17, 2026
0b8d61e
fix(eslint-plugin): judge only the values a spread cannot overwrite
allxsmith Sep 17, 2026
58599d1
fix(eslint-plugin): membership-test the shade before naming the class
allxsmith Sep 17, 2026
b1ab225
docs(eslint-plugin): state the CommonJS defect, not one Node's symptom
allxsmith Sep 17, 2026
ff4512a
fix(bestax-mcp): restamp the index after the valid-values docs edit
allxsmith Sep 17, 2026
ed3ddf9
fix(eslint-plugin): report both spellings of a `true` helper value
allxsmith Sep 17, 2026
a4028ec
fix(eslint-plugin): guard the textColor rewrite the way replacements …
allxsmith Sep 17, 2026
a350ba8
fix(eslint-plugin): a `true` display no longer buys silence on inert …
allxsmith Sep 17, 2026
1d17682
refactor(eslint-plugin): name the line between unreadable and knowabl…
allxsmith Sep 17, 2026
db7547b
test(eslint-plugin): give the generator's guards a seam, and type the…
allxsmith Sep 17, 2026
30ef3de
fix(eslint-plugin): a readable null is still nullish
allxsmith Sep 17, 2026
65e7c63
chore(eslint-plugin): drop the devDependency nothing imports
allxsmith Sep 17, 2026
b753f60
docs(eslint-plugin): say what the nullish guard does, and drop two ea…
allxsmith Sep 17, 2026
359fcf3
test(bulma-ui): load the export map instead of describing it
allxsmith Sep 17, 2026
a534fb6
test(bulma-ui): resolve the subpath by specifier, not by path
allxsmith Sep 17, 2026
ed9a9d7
test: load the plugin's published entry, and stop the guard skipping
allxsmith Sep 17, 2026
1346973
feat(bulma-ui): export the other-helper value tuples
allxsmith Sep 18, 2026
15fced4
feat(eslint-plugin): check the other-helper props now that they have …
allxsmith Sep 18, 2026
e97d609
fix(bulma-ui): give the constants subpath a CommonJS types target
allxsmith Sep 18, 2026
b326ce5
fix(eslint-plugin): stop reporting `radius` on Theme, which is a CSS …
allxsmith Sep 18, 2026
f706137
test(bulma-ui): derive the re-export check from the module it checks
allxsmith Sep 18, 2026
f622452
docs(bulma-ui): state what the ./constants subpath actually serves
allxsmith Sep 18, 2026
db3e07e
docs(eslint-plugin): say precisely why `radius` on Theme is unreportable
allxsmith Sep 18, 2026
035c8f5
test(eslint-plugin): pin that the Theme exception resolves, not name-…
allxsmith Sep 18, 2026
46cd278
test(eslint-plugin): widen the collision guard past the value table
allxsmith Sep 18, 2026
4f69e20
fix(bulma-ui): catch the other shape a declaration specifier can take
allxsmith Sep 18, 2026
85fd556
fix(eslint-plugin): withhold the color fix when the name is doubled
allxsmith Sep 18, 2026
62a0cf3
docs(eslint-plugin): correct the claim that a CommonJS config cannot …
allxsmith Sep 18, 2026
6ad374a
test(eslint-plugin): make the documented examples a gate
allxsmith Sep 18, 2026
0597580
feat(bulma-ui): add the white-bis and white-ter colours the CSS alrea…
allxsmith Sep 18, 2026
d951c2f
fix(bestax-migrate): white-bis and white-ter are bestax colours now
allxsmith Sep 18, 2026
7c617a6
fix(bulma-ui): warn on the new white shades as component modifiers
allxsmith Sep 18, 2026
790f644
test(eslint-plugin): check which rule a documented ✗ example fires
allxsmith Sep 18, 2026
9c40fb6
test(bulma-ui): hold the colour tuples to the stylesheet in both dire…
allxsmith Sep 18, 2026
0e64685
docs(skills): stop the shipped skills stating the old colour facts
allxsmith Sep 18, 2026
867d2f1
test(bulma-ui): cast the invalid fixtures to never, not any
allxsmith Sep 18, 2026
1df5998
docs: delete the orphaned colour footnote on the Control page
allxsmith Sep 18, 2026
a469ff8
test(eslint-plugin): cover the throw that refuses a corrupt metadata …
allxsmith Sep 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ React component library for **Bulma v1** in TypeScript. pnpm monorepo orchestrat
- `bestax-migrate/` — the `bestax-migrate` codemod CLI (has its own CLAUDE.md)
- `bestax-mcp/` — the `bestax-mcp` MCP server; its `data/` index is **generated**
(has its own CLAUDE.md)
- `eslint-plugin/` — `@allxsmith/eslint-plugin-bestax`, lint rules for the library;
its `src/generated/` metadata is **generated** (has its own CLAUDE.md)
- `skills/` — Agent Skills, a **shipped product** bundled into create-bestax (has its own CLAUDE.md)
- `telemetry-worker/` — Cloudflare Worker ingesting the CLIs' opt-in telemetry
(deployed from CI by `deploy-worker.yml` — a merged change under it ships to
Expand All @@ -20,6 +22,8 @@ React component library for **Bulma v1** in TypeScript. pnpm monorepo orchestrat
- `scripts/gen-component-catalog.mjs` — generates the skill component catalog (`pnpm gen:catalog`)
- `scripts/gen-mcp-index.mjs` — generates the MCP server's data index (`pnpm gen:mcp`)
- `scripts/gen-skills-rosters.mjs` — writes the skill install rosters from `skills/` (`pnpm gen:skills`)
- `scripts/gen-eslint-meta.mjs` — generates the ESLint plugin's component metadata
(`pnpm gen:eslint-meta`)

## Toolchain

Expand All @@ -29,8 +33,8 @@ Node 22 locally (`.nvmrc`; CI runs Node 24) and `pnpm@11.9.0` (pinned via `packa
## Commands

```bash
pnpm all # the pre-PR gate: build, typecheck, test+coverage, bundle:stats, lint, format:check, storybook build
pnpm test # jest (bulma-ui + create-bestax + bestax-migrate + bestax-mcp)
pnpm all # the pre-PR gate: build, typecheck, test+coverage, bundle:stats, conformance, the three staleness checks, lint, format:check, storybook build
pnpm test # jest (bulma-ui + create-bestax + bestax-migrate + bestax-mcp + eslint-plugin)
pnpm test:coverage # coverage — thresholds live in each package's jest config (see below)
pnpm lint # eslint
pnpm typecheck # tsc --noEmit (each package's build program)
Expand All @@ -39,7 +43,8 @@ pnpm format # prettier --write (format:check to verify; covers md/mdx to
pnpm gen:catalog # regenerate the skills component catalog (CI fails if stale)
pnpm gen:mcp # regenerate the MCP server's data index (CI fails if stale)
pnpm gen:skills # regenerate the skill install rosters (conformance fails if stale)
pnpm gen # all four generators (api docs, catalog, MCP index, skill rosters)
pnpm gen:eslint-meta # regenerate the ESLint plugin's metadata (in `pnpm all`; no CI step yet)
pnpm gen # every generator (api docs, catalog, MCP index, skill rosters, eslint metadata)
pnpm docs # Docusaurus dev server :3000
pnpm storybook # Storybook dev server :6006
pnpm exec turbo run test --filter=@allxsmith/bestax-bulma # scope any task to one package
Expand Down Expand Up @@ -87,7 +92,7 @@ Conventional Commits, enforced by commitlint (husky `commit-msg` hook) and consu
semantic-release. Two repo-specific rules:

- Commits of type `feat|fix|perf|refactor|style|revert` **must** use a scope of `bulma-ui`, `docs`,
`create-bestax`, `bestax-migrate`, or `bestax-mcp` — an unscoped commit of any of these
`create-bestax`, `bestax-migrate`, `bestax-mcp`, or `eslint-plugin` — an unscoped commit of any of these
scope-gated types is rejected
(`RELEASE_SCOPES` in `commitlint.config.js` is the source of truth). One exception worth
knowing: commitlint's default ignores skip git's own `Revert "…"` messages, so the hook cannot
Expand Down Expand Up @@ -135,8 +140,8 @@ Full versioning details (breaking-change footers, tag formats): `VERSIONING.md`.
and every miss granted the exemption. A workspace **sibling** in `dependencies` or
`optionalDependencies` is separately a violation however the specifier is spelled (#537), and
the only way through is a line in `SIBLING_RUNTIME_DEPS` — same declared shape — for a
package that depends on a sibling at runtime on purpose (#644: the three CLIs on
`@allxsmith/bestax-bulma`, the way bulma-ui declares `bulma`); the test holds that declaration
package that depends on a sibling at runtime on purpose (#644: the three CLIs and
the ESLint plugin on `@allxsmith/bestax-bulma`, the way bulma-ui declares `bulma`); the test holds that declaration
to the real manifests, so a removed dependency cannot leave a standing exemption.

## Workflow
Expand Down
10 changes: 5 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ Runs the real commit analysis + next-version calc, but publishes nothing:

```bash
export GITHUB_TOKEN=<a token with repo read> # the github plugin needs it even in dry-run
for pkg in bulma-ui create-bestax bestax-migrate bestax-mcp; do
for pkg in bulma-ui create-bestax bestax-migrate bestax-mcp eslint-plugin; do
( cd "$pkg" && pnpm exec semantic-release --dry-run --no-ci )
done
```
Expand Down Expand Up @@ -357,7 +357,7 @@ The short version for contributors:

## Semantic Release & Publishing

We use [Semantic Release](https://semantic-release.gitbook.io/) to automate publishing of every package to npm: `bulma-ui` as [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma), plus [`create-bestax`](https://www.npmjs.com/package/create-bestax), [`bestax-migrate`](https://www.npmjs.com/package/bestax-migrate) and [`bestax-mcp`](https://www.npmjs.com/package/bestax-mcp).
We use [Semantic Release](https://semantic-release.gitbook.io/) to automate publishing of every package to npm: `bulma-ui` as [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma), plus [`create-bestax`](https://www.npmjs.com/package/create-bestax), [`bestax-migrate`](https://www.npmjs.com/package/bestax-migrate), [`bestax-mcp`](https://www.npmjs.com/package/bestax-mcp) and `eslint-plugin` as [`@allxsmith/eslint-plugin-bestax`](https://www.npmjs.com/package/@allxsmith/eslint-plugin-bestax).

- Use [Conventional Commits](https://www.conventionalcommits.org/) to trigger releases — see [Commit Message Guidelines](#commit-message-guidelines).
- **Packages version and release independently, keyed off the commit scope** — `feat(bulma-ui)` releases only bestax-bulma. See [`VERSIONING.md`](./VERSIONING.md).
Expand All @@ -369,7 +369,7 @@ Publishing authenticates with npm via [OIDC trusted publishing](https://docs.npm

For this to work, each published package must have a trusted publisher configured **once** on npmjs.com (Package → Settings → Trusted Publisher):

- Packages: `@allxsmith/bestax-bulma`, `create-bestax`, `bestax-migrate` and `bestax-mcp` — every publishable package, and a missing entry fails the publish _after_ the release commit and tag are pushed
- Packages: `@allxsmith/bestax-bulma`, `create-bestax`, `bestax-migrate`, `bestax-mcp` and `@allxsmith/eslint-plugin-bestax` — every publishable package, and a missing entry fails the publish _after_ the release commit and tag are pushed
- Provider: **GitHub Actions**
- Repository: `allxsmith/bestax`
- Workflow: `ci.yml`
Expand All @@ -396,8 +396,8 @@ commitlint via the husky `commit-msg` hook ([`commitlint.config.js`](./commitlin
- **Format:** `<type>(<scope>): <subject>` — imperative subject, blank line, then an optional
body with bullet points and context.
- **Release types need a scope:** commits of type `feat`, `fix`, `perf`, `refactor`, `style`
or `revert` **must** use a scope of `bulma-ui`, `docs`, `create-bestax`, `bestax-migrate`
or `bestax-mcp` (repo-specific commitlint rule — the scope decides which package releases,
or `revert` **must** use a scope of `bulma-ui`, `docs`, `create-bestax`, `bestax-migrate`,
`bestax-mcp` or `eslint-plugin` (repo-specific commitlint rule — the scope decides which package releases,
see [`VERSIONING.md`](./VERSIONING.md)). One correction worth knowing about `revert`:
a scoped conventional `revert(<scope>): …` **releases nothing** — the only revert rule is
commit-analyzer's default `{ revert: true, release: 'patch' }`, keyed on the angular
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,15 @@ function Root() {

## 📦 What's in this repo

| Path | Package | What it is |
| ------------------------------------ | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| [`bulma-ui/`](bulma-ui/) | [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) | The component library |
| [`create-bestax/`](create-bestax/) | [`create-bestax`](https://www.npmjs.com/package/create-bestax) | Project scaffolder — `npm create bestax@latest` |
| [`bestax-migrate/`](bestax-migrate/) | [`bestax-migrate`](https://www.npmjs.com/package/bestax-migrate) | Codemods for migrating existing apps from other React Bulma libraries |
| [`bestax-mcp/`](bestax-mcp/) | [`bestax-mcp`](https://www.npmjs.com/package/bestax-mcp) | MCP server — component props, examples and skills for AI coding agents |
| [`docs/`](docs/) | — | Docusaurus source of [bestax.io](https://bestax.io) |
| [`skills/`](skills/) | — | [Agent Skills](https://bestax.io/docs/skills/intro) for coding agents (also bundled into `create-bestax`) |
| Path | Package | What it is |
| ------------------------------------ | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| [`bulma-ui/`](bulma-ui/) | [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) | The component library |
| [`create-bestax/`](create-bestax/) | [`create-bestax`](https://www.npmjs.com/package/create-bestax) | Project scaffolder — `npm create bestax@latest` |
| [`bestax-migrate/`](bestax-migrate/) | [`bestax-migrate`](https://www.npmjs.com/package/bestax-migrate) | Codemods for migrating existing apps from other React Bulma libraries |
| [`bestax-mcp/`](bestax-mcp/) | [`bestax-mcp`](https://www.npmjs.com/package/bestax-mcp) | MCP server — component props, examples and skills for AI coding agents |
| [`eslint-plugin/`](eslint-plugin/) | [`@allxsmith/eslint-plugin-bestax`](https://www.npmjs.com/package/@allxsmith/eslint-plugin-bestax) | ESLint rules — catches helper-prop values the library silently drops |
| [`docs/`](docs/) | — | Docusaurus source of [bestax.io](https://bestax.io) |
| [`skills/`](skills/) | — | [Agent Skills](https://bestax.io/docs/skills/intro) for coding agents (also bundled into `create-bestax`) |

The published packages are versioned and released independently.

Expand Down
23 changes: 15 additions & 8 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@

Security fixes land on the **latest release line only** — currently
`@allxsmith/bestax-bulma` 5.x, `create-bestax` 4.x, `bestax-migrate` 2.x, and
`bestax-mcp` 1.x. All four packages release automatically from `main`
(semantic-release), so the latest published version is always the patched one.
`bestax-mcp` 1.x. Those release automatically from `main` (semantic-release),
so the latest published version is always the patched one.
Older majors may still work but receive no security updates; please upgrade.

| Package | Supported | Unsupported |
| ------------------------- | ------------ | ----------- |
| `@allxsmith/bestax-bulma` | 5.x (latest) | < 5.0 |
| `create-bestax` | 4.x (latest) | < 4.0 |
| `bestax-migrate` | 2.x (latest) | < 2.0 |
| `bestax-mcp` | 1.x (latest) | — |
`@allxsmith/eslint-plugin-bestax` has no supported line yet. The only version
on the registry is a `0.0.0-development` placeholder, published by hand to
claim the name so a trusted publisher could be attached to it, and it carries
no provenance because no laptop publish can. Its supported line starts at the
first release from `main`.

| Package | Supported | Unsupported |
| --------------------------------- | -------------------- | ----------- |
| `@allxsmith/bestax-bulma` | 5.x (latest) | < 5.0 |
| `create-bestax` | 4.x (latest) | < 4.0 |
| `bestax-migrate` | 2.x (latest) | < 2.0 |
| `bestax-mcp` | 1.x (latest) | — |
| `@allxsmith/eslint-plugin-bestax` | none yet (see below) | — |

## Supply-Chain Security

Expand Down
34 changes: 20 additions & 14 deletions VERSIONING.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,42 @@
# Independent Versioning Strategy

`@allxsmith/bestax-bulma`, `create-bestax`, `bestax-migrate`, and `bestax-mcp` are versioned
`@allxsmith/bestax-bulma`, `create-bestax`, `bestax-migrate`, `bestax-mcp`, and
`@allxsmith/eslint-plugin-bestax` are versioned
and released **independently**. Each package releases only when a commit is scoped to it — the
version numbers are unrelated (e.g. bestax-bulma 5.x alongside create-bestax 3.x).

The source of truth is the `releaseRules` in each package's semantic-release config:
[`bulma-ui/release.config.js`](./bulma-ui/release.config.js),
[`create-bestax/release.config.js`](./create-bestax/release.config.js),
[`bestax-migrate/release.config.js`](./bestax-migrate/release.config.js), and
[`bestax-mcp/release.config.js`](./bestax-mcp/release.config.js).
[`bestax-migrate/release.config.js`](./bestax-migrate/release.config.js),
[`bestax-mcp/release.config.js`](./bestax-mcp/release.config.js), and
[`eslint-plugin/release.config.js`](./eslint-plugin/release.config.js).

## Release Rules

A commit releases **only** the package its scope names. Representative examples — the same
`feat`/`fix`/`perf`/`refactor`/`style` and `BREAKING CHANGE:` rules apply to every package
through its own scope:

| Commit | bestax-bulma | create-bestax | bestax-migrate | bestax-mcp |
| ----------------------------------------------------------------- | ------------ | ------------- | -------------- | ---------- |
| `feat(bulma-ui): …` | minor | — | — | — |
| `fix(bulma-ui): …` | patch | — | — | — |
| `perf/refactor/style(bulma-ui): …` | patch | — | — | — |
| `feat(create-bestax): …` | — | minor | — | — |
| `fix(bestax-migrate): …` | — | — | patch | — |
| `feat(bestax-mcp): …` | — | — | — | minor |
| `feat(bulma-ui): …` + `BREAKING CHANGE:` footer | major | — | — | — |
| `docs: …`, `chore: …`, `ci: …`, `test: …`, `build: …` (any scope) | — | — | — | — |
| Commit | bestax-bulma | create-bestax | bestax-migrate | bestax-mcp | eslint-plugin |
| ----------------------------------------------------------------- | ------------ | ------------- | -------------- | ---------- | ------------- |
| `feat(bulma-ui): …` | minor | — | — | — | — |
| `fix(bulma-ui): …` | patch | — | — | — | — |
| `perf/refactor/style(bulma-ui): …` | patch | — | — | — | — |
| `feat(create-bestax): …` | — | minor | — | — | — |
| `fix(bestax-migrate): …` | — | — | patch | — | — |
| `feat(bestax-mcp): …` | — | — | — | minor | — |
| `feat(eslint-plugin): …` | — | — | — | — | minor |
| `feat(bulma-ui): …` + `BREAKING CHANGE:` footer | major | — | — | — | — |
| `docs: …`, `chore: …`, `ci: …`, `test: …`, `build: …` (any scope) | — | — | — | — | — |

Notes:

- **Breaking changes require a `BREAKING CHANGE:` footer** in the commit body. The angular
commit-analyzer preset does **not** parse `feat(bulma-ui)!:` bang headers.
- Commits of a scope-gated type (`feat`, `fix`, `perf`, `refactor`, `style`, `revert`) **must**
carry a scope of `bulma-ui`, `docs`, `create-bestax`, `bestax-migrate`, or `bestax-mcp` —
carry a scope of `bulma-ui`, `docs`, `create-bestax`, `bestax-migrate`, `bestax-mcp`, or
`eslint-plugin` —
enforced by commitlint ([`commitlint.config.js`](./commitlint.config.js)) via the husky
`commit-msg` hook. This is what guarantees the per-scope release rules can't be bypassed by
an unscoped commit.
Expand All @@ -57,6 +61,8 @@ Each package tags and logs its own releases:
- `create-bestax@X.Y.Z` tags, changelog at `create-bestax/CHANGELOG.md`
- `bestax-migrate@X.Y.Z` tags, changelog at `bestax-migrate/CHANGELOG.md`
- `bestax-mcp@X.Y.Z` tags, changelog at `bestax-mcp/CHANGELOG.md`
- `@allxsmith/eslint-plugin-bestax@X.Y.Z` tags, changelog at
`eslint-plugin/CHANGELOG.md`

## Release Process

Expand Down
Loading
Loading