Repository navigation
Releases: cuonggt/kaze
Release list
v2.1.1
Fixed
-
User-visible text now reads the same across the three stacks and within a page. Hotwire's login button said "Login" where React and Vue said "Log in", which is what prompted this — but the sweep found the real problem was that the 2.0.0 settings area introduced sentence case ("Profile information", "Delete account") while the auth pages kept the title case inherited from Breeze ("Reset Password", "Confirm Password"), so the two conventions met inside the same screen. The delete-account page had a "Delete account" heading directly above a "Delete Account" button.
Everything settles on sentence case, matching the settings area and Laravel's current kits: "Log in", "Log out", "Reset password", "Confirm password", "Current password", "New password", "Delete account", "Email password reset link", "Resend verification email", and the "Forgot password" and "Email verification" page titles. Mailer copy is left in title case — a different surface, and Laravel's reset email keeps it too.
Documentation
-
Screenshots and badges in the README. A starter kit whose selling point is what it looks like had no picture of itself anywhere — someone evaluating Kaze had to install it to find out. Three captures of the real scaffolded application cover the sidebar shell, the settings area and both themes, at 48 KB in total and outside the gem's packaged files.
-
A README section on the frontend. The 2.0.0 redesign is the largest change this project has had and the README described none of it — what shadcn/ui means here, that the primitives are yours to edit, how to add more with
npx shadcn@latest add, the capitalised@/Componentsalias that will bite anyone hand-writing an import, the token and appearance systems, and why the Hotwire stack hand-rolls its own equivalents.
Internal
-
A test suite for the gem itself, run by
rake testand by a newGem Testsjob in CI. Until now the only automated coverage was the scaffolded applications' own tests, which exercise the stubs but never the code that copies them.The bulk of it covers
kaze upgrade, since that is the part that deletes files from a real application: that a directory is pruned only once empty, that one still holding someone else's work survives along with the file in it, that nothing aboveapp/is ever touched, and that a path missing from the application is skipped rather than raised on. The rest pins the removal manifests — no listed path may still be shipped by the stubs, which would haveupgradedelete a file the install puts straight back — and checks thatlib/kaze/version.rbmatches the newest changelog heading, so a release cannot ship a version the changelog does not describe.The tests are excluded from the built gem.
v2.1.0
Added
-
A
kaze upgrade [STACK]command. Kaze copies files into an application and does not own them afterwards, sokaze installcannot tell a leftover from an older version apart from something you wrote, and has always left both alone.upgraderesolves that by asking instead of guessing: it lists the files an earlier Kaze installed that this version no longer ships, waits for you to agree, removes them, and then runs the normal install.Only paths Kaze itself shipped are ever offered — the list per stack is fixed in the source, so nothing you added alongside them can be caught by it, and a directory is removed only once it is empty.
--dry-runprints the list and stops;--forceskips the prompt for scripts. Declining exits non-zero and changes nothing.This replaces the manual file list in the 2.0.0 upgrade notes below. On the React stack it is the difference between an upgraded application building and not:
tsctypechecks every file underapp/javascript, so the oldPages/Profile/Edit.tsxfails the build until it is gone.
v2.0.1
Fixed
-
kaze installrun throughbundle execno longer fails to build gems with native extensions. Bundler exportsRUBYOPTandBUNDLE_*so child processes join its bundle, which is wrong for a nested bundler call: thebundle addthat kaze shells out to inherited them, andextconf.rbthen loadedbundler/setupand tried to resolve a lockfile needing the very gem it was about to compile, failing withCould not find bcrypt-… in locally installed gems. The bundler shell-outs now run insideBundler.with_unbundled_env.The README's own instructions —
gem install kazethenkaze install— were never affected, because that runs outside bundler. This reachedbundle exec kaze install, which is how kaze's CI invokes it and how anyone who adds kaze to their Gemfile would.
v2.0.0
Added
-
The frontend is rebuilt on shadcn/ui, following Laravel's react and vue starter kits (#27, #28, #29, #30, #31, #32, #33, #34). shadcn copies source into the project rather than shipping a package, which is how Kaze already works, so the primitives are vendored into
Components/uiand are yours to edit.A design token layer comes with it. Colour is now
bg-background,text-muted-foreground,border-sidebar-borderand so on, resolving through oklch variables defined once per stylesheet, instead ofbg-white dark:bg-gray-800repeated per element. Acomponents.jsonrecords the aliases sonpx shadcn@latest add <component>lands in the right place — note that Kaze uses a capitalised@/Components, which that file already reflects.Thirteen primitives for each Inertia stack: button, input, label, checkbox, dialog, dropdown-menu, separator, skeleton, sheet, tooltip, avatar, breadcrumb and sidebar, plus a
cnhelper inlib/utils. React builds on Radix, Vue on reka-ui. -
A collapsible sidebar replaces the top navigation bar in all three stacks. It collapses to icons, becomes a drawer below
md, and remembers its state in asidebar_statecookie that the server reads back, so the first paint matches the last choice rather than flashing open.There is no shadcn for Hotwire, so its sidebar is hand-rolled in Alpine and ERB against the same tokens, with the lucide icons inlined through a new
IconComponentsince Hotwire has no npm. -
A settings area at
/settings/profile,/settings/passwordand/settings/appearance, replacing the single profile page (#35, #36)./settingsredirects to the profile page. Each has its own breadcrumb and page title, and the delete-account form stays on the profile page.
Changed
-
The profile page has moved and its routes with it.
/profileis now/settings/profile, and password updates post to/settings/passwordrather than to the profile page. The route helper names are unchanged —profile_edit_pathstill exists, it just points somewhere new — so an application that uses the helpers rather than hard-coded paths needs no edit.password_edit_pathandappearance_edit_pathare new.ProfileControllerandPasswordControllerbecomeSettings::ProfileController,Settings::PasswordControllerandSettings::AppearanceController. -
The
darkvariant is redefined, in all three stylesheets:/* was */ @custom-variant dark (&:where(.dark, .dark *)); /* now */ @custom-variant dark (&:is(.dark *));
:where()contributes no specificity, so adark:utility tied with its light counterpart and won or lost on the order Tailwind happened to emit them in —dark:text-blacklost totext-whiteon the same element.:is()gives the variant the higher specificity, which is what Laravel's kits use. If you have written adark:override that was silently losing, it will now apply; if you wrote one that depended on losing, it will not. -
The Vue stack pins
typescriptto^5.9.3, down from^7.0.2(#30).@vue/compiler-sfcneeds filesystem access to resolve prop types that cross a package boundary, which the vendored primitives do, and the resolver it uses is not compatible with TypeScript 7. The React stack stays on 7.
Removed
- The hand-rolled components the shadcn primitives replace:
PrimaryButton,SecondaryButton,DangerButton,TextInput,InputLabel,Checkbox,Modal,Dropdown,NavLinkandResponsiveNavLinkfrom both Inertia stacks,DropdownLinkfrom the Vue stack, andNavLinkComponentandResponsiveNavLinkComponentfrom Hotwire. The buttons, inputs and labels map ontoButton,InputandLabelwith a variant; the navigation links have no successor, because the sidebar replaced what used them.
Fixed
kaze installexits non-zero when it fails. Every step is guarded, so the installer already stopped at the first failure and withheld its success message — but the process still exited 0, so a script or CI job saw a green step over a half-installed application. This is the same class of silent failure as #11, in the exit code rather than the output. Anything that runskaze installunattended and currently passes over a failure will now fail, which is the point.
Upgrading
Kaze scaffolds rather than vendors, so nothing changes under an existing application on its own. Re-running kaze install over one built with 1.4.0 or earlier does not remove what this release replaced — the installer copies files in and never deletes, deliberately, since by then they are yours and may be edited. The replaced files are left behind for you to delete:
| stack | left behind |
|---|---|
| all | app/controllers/profile_controller.rb, app/controllers/password_controller.rb |
| react, vue | app/javascript/Components/{PrimaryButton,SecondaryButton,DangerButton,TextInput,InputLabel,Checkbox,Modal,Dropdown,NavLink,ResponsiveNavLink}, DropdownLink on vue, and the whole of app/javascript/Pages/Profile/ |
| hotwire | app/components/{nav_link,responsive_nav_link}_component.rb, app/views/layouts/_navigation.html.erb, and the whole of app/views/profile/ |
On the React stack this is not optional: tsc typechecks every file under app/javascript, and the stale Pages/Profile/Edit.tsx still passes a header prop that the layout no longer takes, so the build fails until that directory is gone. Vue and Hotwire build and run with the stale files in place — they are dead weight rather than a break, since nothing routes to them any more.
v1.4.0
Added
-
An appearance preference — light, dark or system — on the profile page of all three stacks (#26). The stubs already carried 315
dark:classes, but nothing could reach them:dark:followedprefers-color-scheme, so an application took whatever the operating system said. The choice is stored inlocalStorage, and system follows the device and tracks it live.Each stylesheet now redefines the variant, since Tailwind v4 no longer configures dark mode in JavaScript:
@custom-variant dark (&:where(.dark, .dark *));
The layouts apply the resulting
darkclass in an inline<head>script before first paint, so the page never flashes the wrong theme. A consequence worth knowing: the theme now depends on JavaScript, so with scripting disabled an application always renders light where it previously followed the operating system.
Fixed
- Dark mode gaps that were already broken for anyone whose operating system was set to dark, and which the preference control made obvious. React's
AuthenticatedLayoutcarried onedark:class where Vue's had fifteen, leaving a white navigation bar and header above a dark page; the missing variants are ported from the Vue layout. Four wrappers lackeddark:bg-gray-900, leaving a light grey page behind dark cards — hotwire's application layout, React'sAuthenticatedLayoutandGuestLayout, and the Inertia ERB wrappers for both stacks.
Full Changelog: v1.3.1...v1.4.0
v1.3.1
Changed
required_ruby_versionis now>= 3.4.0, up from>= 3.1.0. Rails 8.1 cannot be parsed by Ruby 3.3 — actionview uses syntax Ruby 3.4 introduced — so a Kaze-scaffolded application has never actually worked below 3.4, and the gem page advertised a floor that the README already contradicted.
Full Changelog: v1.3.0...v1.3.1
v1.3.0
Changed
-
Both Inertia stacks move to Inertia.js 3 (#25). The versions are chained rather than independent: Inertia 3's React adapter requires React 19, and
@vitejs/plugin-react6 requires Vite 8, so the whole front end moves together.package from to @inertiajs/react, @inertiajs/vue3 ^2.0.0 ^3.9.1 react, react-dom ^18.2.0 ^19.3.1 @vitejs/plugin-react ^4.2.0 ^6.1.2 @vitejs/plugin-vue ^5.0.5 ^6.0.10 typescript ^5.6.3 ^7.0.2 vite ^6.4.4 ^8.3.4 @types/node ^18.13.0 ^26.6.5 vue ^3.4.27 ^3.5.44 vue-tsc ^2.0.21 ^3.3.13 vite-plugin-rails ^0.5.0 ^0.6.0 -
The React entrypoint resolves pages differently. Inertia 3 narrowed its resolver type so that a promise of a module object is no longer accepted, and
resolvePageComponentnow unwrapsdefaultitself and is typed with the exportedResolvedComponent.
Added
- Both Inertia stacks install
config/initializers/inertia_rails.rb. Inertia 3 reads the initial page from a<script type="application/json">element and expects adata-inertiahead attribute;inertia_railssupports both but defaults to the v2 behaviour, so without this the client loads and renders nothing. The initializer also setsalways_include_errors_hash, which becomes the default in InertiaRails 4.0.
Internal
- Dependabot watches bundler, npm and GitHub Actions weekly. Majors are held back for the two stub manifests, since a major there changes the starter kit and needs an install-and-build pass across all three stacks (#20)
- The nightly schedule lives in its own workflow (#19). GitHub disables a workflow carrying a
schedule:trigger after 60 days without repository activity, and disables its other triggers with it — which is how CI came to be switched off for the twelve months before 1.2.0. An idle stretch can now cost only the nightly run, never pull request CI. actions/checkout4 → 7, prettier 3.3.2 → 3.9.10 (#21, #22)
Full Changelog: v1.2.1...v1.3.0
v1.2.1
No changes to scaffolding behaviour. Packaging, documentation and CI only.
Added
- This changelog. It ships in the gem and is linked from the RubyGems page through
changelog_uri
Changed
homepageand the README point atgithub.com/cuonggt/kaze, the current repository URL, rather than thegtkvnname that redirects to it- Updated development dependencies, clearing 62 Dependabot advisories against
Gemfile.lock. The lockfile is not shipped in the gem, so this affects contributors and CI only (#16) - CI reports a single stable
Stub Testscheck alongside the per-stack jobs, so branch protection no longer depends on job names generated from the test matrix (#18)
Documentation
- Recorded that Kaze targets Rails 8.1 on Ruby 3.4, and that Rails 8.0 is not supported (#17)
Full Changelog: v1.2.0...v1.2.1
v1.2.0
Fixed
kaze installno longer fails on current Rails. Thebin/bundlefallback added in 1.1.0 only coveredinstall_gemsandremove_gems; all three stacks still invokedbin/bundledirectly to addtailwindcss-rails. Rails has not generated that binstub since 7.1, so the step failed,tailwindcss-railsnever reached the Gemfile, and the subsequenttailwindcss:buildaborted withUnrecognizedCommandError(#11)- A failed Tailwind or Node step now aborts the install instead of printing
Kaze scaffolding installed successfully.over it. Exit statuses from these commands were discarded, so a completely failed build still reported success run_commandreads subprocess output as UTF-8 and scrubs invalid bytes. Where no locale is configured — Docker images, CI containers, cron — Ruby tagged output as US-ASCII and any non-ASCII byte aborted the install withinvalid byte sequence in US-ASCII. Vite triggered this on every Inertia install, via the check mark in its build summary
Changed
- All three stacks migrated to Tailwind CSS v4 (#14).
tailwindcss-railsmoves to~> 4.0,config/tailwind.config.jsis removed, and the stylesheet entry point moves fromapp/assets/stylesheets/application.tailwind.csstoapp/assets/tailwind/application.css, whichtailwindcss-rails4.x expects. Configuration now lives in CSS: the Inter font as@theme, the forms plugin as@plugin, and the formercontentglobs as@sourcedirectives. 76 renamed utilities were updated across the stubs, and Preflight'scursor: defaulton buttons is restored tocursor: pointer tailwindcss,@tailwindcss/forms,autoprefixerandpostcssremoved from the Inertia stubs. The gem's CLI builds the CSS and Vite only imports the result, so nothing consumed them- Vite bumped to
^6.4.4in the Inertia stubs, clearing two high and four moderate advisories (#12)
Together these take a freshly scaffolded Inertia application from seven npm advisories, five of them high, to zero.
Internal
- CI runs against Rails 8.1 on Ruby 3.4, reports every matrix job rather than cancelling siblings on the first failure, and passes for the first time (#13, #15)
Full Changelog: v1.1.0...v1.2.0