Migrate an existing React app to @allxsmith/bestax-bulma on Bulma v1, from raw Bulma CSS classes on plain JSX (className="button is-primary") or in static HTML pages and templates styled with Bulma, or from an unmaintained React Bulma library (react-bulma-components v4, rbx v2, bloomer 0.6). Run the bestax-migrate codemod, then resolve every TODO(bestax-migrate) comment it leaves using the per-source mapping references. Use when a React app styles its markup with Bulma classes and wants bestax components instead, when static HTML pages or templates styled with Bulma should become React components, when a repo imports react-bulma-components, rbx or bloomer, when TODO(bestax-migrate) comments are present in a codebase, or when asked to convert Bulma classNames to bestax-bulma.
95%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
@allxsmith/bestax-bulma is an actively maintained React library for Bulma v1. The
bestax-migrate codemod automates most of the conversion from an unmaintained predecessor;
this skill drives the codemod and finishes what it flags.
The codemod's first argument names the library you are migrating from. Check the app's
package.json and imports:
| Source | Argument | References |
|---|---|---|
react-bulma-components v4 (unmaintained since 2022, Bulma 0.9.x) | react-bulma-components | references/react-bulma-components/ |
rbx v2 (abandoned 2019, pins Bulma 0.7.5 plus four extensions) | rbx | references/rbx/ |
bloomer 0.6 (archived 2018, Bulma 0.6 era, React 16 + create-react-class) | bloomer | references/bloomer/ |
Raw Bulma classes on plain JSX (<div className="box">), no React Bulma library | bulma-classes | references/bulma-classes/ |
Static HTML pages or templates styled with Bulma (<div class="box">) | bulma-classes | references/bulma-classes/ |
Everything below is written as <source>; substitute the argument from that table. The
reference paths follow the same split — references/<source>/component-map.md,
prop-map.md, unmappables.md — while
references/css-migration.md is shared, because the stylesheet
work is about Bulma, not about which wrapper you came from.
Run these steps in order. Don't hand-convert what the codemod converts automatically.
Dry-run the codemod on the source directory and review the report:
pnpm dlx bestax-migrate <source> src/ --dryFor HTML pages, name a page, or walk a folder with -e html (-e html,htm for .htm pages
too; a plain walk skips them,
since most of it in a React project isn't a page to convert, and reports the Bulma pages it
skipped as html-file:not-included):
pnpm dlx bestax-migrate bulma-classes src/pages/login/index.html --dry
pnpm dlx bestax-migrate bulma-classes -e html src/pages/ --dryEach page becomes a module beside it (index.tsx, or .jsx when the package isn't
TypeScript) whose default export is <Name>Page, named from the file (its folder's for an
index.html). The page stays as it was, and the codemod never writes over a module that's
already there, so a re-run on the page writes nothing: after fixing a TODO, re-run on the
module, which is what each TODO says. Its head, its <html> and <body> attributes and
its scripts become html-* TODOs: put the app-wide parts in the app's index.html and
entry, and port each script's work into the component. Under --css bestax or --css bulma
the module imports the stylesheet in place of the page's Bulma <link>.
A file that fails to parse or transform is marked ✖, listed under failed in the report
and left as it was, and the run exits 1 while every other file still converts. Fix that file
and run the codemod on it again. TODOs alone leave the exit code at 0.
Apply it (same command without --dry), then run the project's formatter — the
codemod preserves surrounding formatting but doesn't prettify what it rewrites.
Besides the components, it also migrates stylesheets (CSS imports →
@allxsmith/bestax-bulma/bestax.css; SCSS @import 'bulma/bulma' + $var overrides
→ @use 'bulma/sass' with (…) plus the bestax extras) and package.json.
Flags: --css bulma|keep for other stylesheet targets, --no-deps to leave
package.json alone. bulma-classes is the exception: it defaults to --css keep,
because the app's own Bulma already styles every class it converts, so its stylesheets
and Bulma version stay unless you pass --css bestax or --css bulma.
Install — the codemod edits package.json but never runs a package manager. Resolve the
retained imports first: a component with no bestax equivalent keeps a trimmed,
TODO-annotated import of the source library, which the manifest step has just removed — so a
clean install leaves those unresolvable. The report names them in a deps entry.
npm install # or pnpm/yarnThe report groups its entries by rule. deps covers every package.json edit —
what was removed, added, or left for you to decide; imports covers a source
import the codemod could not rewrite and left in place; unsupported-file names
a file type it cannot parse (.vue, .astro) that still imports the source;
value-reference marks a component used as a value rather than as JSX. Rules
named component:X and prop:y are per-component and per-prop, and each is
documented in the per-source references/ pages.
The report's peer-deps entries predict install failures: bestax-bulma needs
React 18/19 (react-bulma-components also ran on 17, while rbx and bloomer peer-depended
on React 16 — upgrade react/react-dom first) and its optional Font Awesome peer wants
FA ≥ 6.7 (an app pinned to FA 5 either upgrades or installs with
npm install --legacy-peer-deps).
Resolve every TODO: grep -rn "TODO(bestax-migrate)" src/. Each comment names the
prop/component and a hint. Recipes for every recurring case are in
references/<source>/unmappables.md. Before writing a component by hand, look it up in
references/<source>/component-map.md and its classes in references/<source>/prop-map.md:
they name the component and the prop for each class, which the library's type declarations
only tell you slowly. For form markup (.field, .control, inputs, selects), load the
bestax-form skill too: it covers the label, id and help-text wiring. Delete each comment
as you resolve it.
Finish the stylesheet layer — flagged Sass cases (computed variables,
indented-syntax .sass files), CSS flavor choice, and Bulma 0.9→1 styling changes:
follow references/css-migration.md.
Finish: typecheck/build, and review the rendered app side by side against the pre-migration UI.
Every export of every supported source has a mapping entry, held to that library's real export surface by a coverage test. Imports (named, namespace, and destructuring), component renames, prop renames and value conversions, breakpoint objects, CSS/SCSS stylesheet imports, and package.json dependencies convert automatically.
It flags with TODO(bestax-migrate) instead of guessing: components with no bestax equivalent,
controlled APIs whose shape differs, breakpoints bestax has no prop for, dynamic prop values it
can't rewrite, and props with no counterpart. Files in formats it can't parse (.astro,
.vue, .svelte, .mdx) that import the source library are reported as unsupported-file —
migrate those by hand with the component map. Never "fix" a TODO by silencing it — convert the
code per the references, or deliberately keep the old markup with className styling.
Element and Tile have no
bestax equivalent; renderAs becomes as where supported.bulma@0.7.5 as a direct
dependency plus bulma-badge, bulma-divider, bulma-pageloader and bulma-tooltip, so
the app can finally choose its own Bulma version. rbx's badge and tooltip helper props
become real wrapping <Badge> / <Tooltip> components. Its as is universal, bestax's is
not. Because rbx pinned Bulma 0.7.5, you cross two Bulma majors — expect more visual
drift than the 0.9 → 1 guide alone describes.<i> in a .icon
that carries nothing else assistive tech reads becomes Icon, which hides the .icon
instead, the glyph hidden either way. Such a .icon around a bare glyph, in a link or button
its own aria-label names, becomes Icon too, which hides it, since the label is what a
screen reader reads there. Font Awesome 6's long style names (fa-brands) become the
bestax-icons skill's variant (brands), which renders the short name (fab), the same
style. And Bulma 0.9's is-marginless and is-paddingless,
which style nothing under v1, become m="0" and p="0". Everything else stays as written, with a
TODO when there is something to decide. Static class strings convert, and so does a clsx or
classnames call of strings and conditional classes, where a condition on a flag becomes
its prop (isLoading={busy});
any other computed className gets dynamic-class:<Target>, naming the component the element
would become. Files a Next.js
App Router may render as server components are left alone (rsc), and the manifest gains
@allxsmith/bestax-bulma while the app's Bulma and stylesheets stay (the default
--css keep). Its rules are kind:<name> shaped; see
references/bulma-classes/unmappables.md. An HTML page converts the same way once it is JSX,
and what a component can't carry (the head, scripts, inline handlers, <html> and <body>
classes such as has-navbar-fixed-top) gets an html-* rule with its recipe there.CardHeaderTitle → Card.Header.Title). Most of its is* booleans already are bestax's
(isActive becomes active where bestax names it so; isFullWidth becomes isFullwidth
where bestax has the prop); the work is in isSize/isColor/isAlign (renamed per component), the isDisplay/isHidden
helpers (flattened, arrays and objects included), tag (→ as where bestax has one) and
render (always a TODO). Its icons are className-based and Font Awesome 4 — the biggest
visual risk, see references/bloomer/unmappables.md. The app declared its own Bulma 0.6,
which the codemod bumps; there is no pinned Bulma to free.bulma-classes skips elements that are already
components, never repeats a TODO it already wrote, and drops one that asked for a re-run once
it no longer applies.is* booleans
(isLoading), string size unions (textSize="4"), and as rather than renderAs.allxsmith/bestax
05bf0cb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.