#nobuild support comes to Rails UI
Andy Leverenz

I'm excited to share an update to Rails UI that makes me wonder why we didn't do this sooner. Version 3.3+ embraces the no-build philosophy that Rails 8 is all about, while still keeping the door wide open for folks who need more advanced JavaScript tooling. In short, whether you prefer nobuild or build modes in your monolith Rails app, Rails UI has got you covered.
What has changed?
Rails UI now gives you two paths forward, depending on what your project actually needs:
1. #nobuild mode (The new default)
This is for most of us building apps, prototypes, or anything that doesn't need complex JavaScript tooling. Zero build step. No Node.js. Just Rails and your code.
2. Build Mode
Sometimes you need TypeScript, advanced bundling, or complex JavaScript dependencies. When that's the case, you get complete control over your JavaScript pipeline with esbuild, webpack, bun, or rollup via the jsbundling-rails gem.
Goodbye cssbundling-rails, hello tailwindcss-rails
Previous versions of Rails UI had you manually set up Tailwind CSS with cssbundling-rails. We chose this path for more control over customizations with previous versions of Tailwind CSS.
Going this route, you had to run rails new myapp -c tailwind -j esbuild, manage Tailwind through package.json, and deal with Node.js even when you didn't actually need it for your JavaScript. For CSS, this is mind-numbing at times and never felt quite right to me.
Now with 3.3+ Rails UI handles this automatically using the tailwindcss-rails gem, and it's honestly so much better:
- CSS compiles faster (native binary instead of Node.js)
- Fewer dependencies to manage (no Tailwind in package.json)
- One command to get started
- Works perfectly with both build modes (the main driver for the shift to reduce complexity)
How it works
The beauty of the no-build approach is its simplicity. You create a Rails app, add Rails UI (bundle add railsui), run the installer (rails railsui:install), and you're done.
Your JavaScript loads via an import map from a CDN, Tailwind compiles via the gem, and everything just works. No waiting for builds, no dealing with Node.js unless you actually need it.
When you do need more for a larger team, advanced bundling, or complex JavaScript dependencies, build mode is there. It gives you the complete toolchain: esbuild, webpack, bun, or rollup, whichever fits your workflow. The key difference is that you opt into that complexity only when your project calls for it.
Configuration
As with the start of this project, everything lives in config/railsui.yml. build mode is just one setting among others. Changing modes is as simple as flipping that value and regenerating your assets which can be done via the form on /railsui or by running rails railsui:update.
Switching modes
The flexibility here is real. Start simple with no-build, then switch to a full bundler when your project demands it. Or go the other way strip out the build complexity when you realize you don't need it. Update your config, regenerate assets, and you're running with a different mode. No migrations, no rewrites. Check the README for guidelines on moving between build and nobuild modes if you wish to.
Upgrading from earlier versions
If you're on v3.2 or earlier with cssbundling-rails, there's a migration task that handles most of the work. It installs the new gem, removes Tailwind from your package.json, updates your Procfile, and creates the new CSS structure. Your old CSS file stays put so you can manually migrate any customizations you've made.
Stop using -c tailwind
The most significant change now is that there is no need to create your Rails app with -c tailwind anymore. Rails UI now includes tailwindcss-rails and handles CSS automatically. Using -c tailwind installs cssbundling-rails, which creates conflicts and complexity you or I don't want to debug.
Which mode makes sense?
No-build means no Node.js, no build step, simpler deployment. JavaScript is loaded from a CDN via an import map, as in Rails 8 defaults. It's great for most apps and prototypes.
Build mode requires Node.js and a package manager, but it also provides TypeScript support, bundle optimization, and offline development. Better for production apps with complex JavaScript needs. If you have a highly interactive UI this might be a better fit depending on your needs.
Both use the same fast tailwindcss-rails setup for CSS. Pick whichever matches your project, not what you think you're "supposed" to use.
Smart warnings
The Rails UI installer tries its best to detect your setup and warn you about potential issues like having cssbundling-rails when you should migrate, or using the --build flag without jsbundling-rails installed. If you know what you're doing, skip them with RAILSUI_SKIP_WARNINGS=1.
Existing apps
Already using importmap? Just install the Rails UI gem and run the installer (rails railsui:install). Already using esbuild or webpack? Install with the --build flag. Using cssbundling-rails? Install Rails UI, then run the migration task. It works with whatever you've got.
Why the update?
This aligns the Rails UI with the Rails philosophy: make simple things simple, and complex things possible. Start with nobuild and ship fast. Need TypeScript later? Switch to build mode. Realize you don't need the complexity? Switch back. You're not locked in.
The goal was always to meet you where you are. Now it actually does.
Have feedback, suggestions, or requests for themes? Check out the links below.
Final thoughts
With this update out of the way, I'm busy both building more themes and, ideally, incorporating view_component support. It's all in progress.
Links:
- Documentation
- GitHub Discussions
- Follow on X
- Get full access to Rails UI