loco_motion
Crazy fast Rails development with modern tools and components leveraging ViewComponent, TailwindCSS, DaisyUI and more!

Contents
- About
- Current Status
- Installation
- Using Components
- Guides
- Documentation & Demo
- Developing
- Getting Help
- TODO / Next Steps
About
loco_motion is both a set of philosophies and paradigms for developing robust web applications in Ruby on Rails, as well as a set of gems and tools to help you execute on your vision quickly and reliably.
At its core, LocoMotion is a Rails ViewComponent library that wraps DaisyUI components with a clean, Ruby-first API. It generates semantic, accessible UI elements using Tailwind CSS classes.
It also includes standards and recommendations for your
- Development Environment
- Testing / Debugging
- CSS / Page Markup
- Components / Libraries
- Releasing / Hosting
- and much more!
You can use as much or as little of the frameworks and philosophies provided, and you can customize it all to your heart's content. If you just want the components, jump straight to Installation. If you want the full opinionated project setup, start with the Guides.
Current Status
This project is in active development and many changes occur with every release!
As of v0.5.x, LocoMotion ships with Tailwind 4 and DaisyUI 5. The install approach has changed from previous versions, so please follow the updated instructions below.
[!CAUTION] LocoMotion is in active development. Components are functional but APIs may change between minor releases. Pin to a specific version in production.
Many of the DataInput elements (file input, text input, select dropdown, etc) were built as a base version to start from. DaisyUI 5 redesigned these components significantly, so they are being incrementally improved as we use them in real projects.
Installation
Add the following to your Gemfile and re-run bundle:
# Gemfile
gem "loco_motion-rails", "~> 0.5.2", require: "loco_motion"
Next, create or update your tailwind.config.js to tell Tailwind where to
scan for component class names. In Tailwind 4, this file handles only
content paths — plugins belong in your CSS file (see the
Getting Started guide).
const { execSync } = require('child_process');
let locoBundlePath =
execSync('bundle show loco_motion-rails').toString().trim();
module.exports = {
content: [
`${locoBundlePath}/app/components/**/*.{rb,js,html,haml}`,
'app/components/**/*.{rb,js,html,haml}',
'app/views/**/*.{rb,js,html,haml}',
]
}
[!WARNING] Note that
bundle show loco_motion-railswill output nothing if the gem is not installed or the name is wrong, causing Tailwind to skip all component classes. Make sure the gem name matches exactly.
Next, if you're using any of the components that require JavaScript (like the
Countdown component), you'll need to add the library as a dependency and include
those controllers in your application.js file.
npm add @profoundry-us/loco_motion
or
yarn add @profoundry-us/loco_motion
Then inside your application.js file, make sure to import and register the
relevant controllers.
import { Application } from "@hotwired/stimulus"
import {
CountdownController,
ThemeController,
AlertController,
CallyInputController
} from "@profoundry-us/loco_motion"
const application = Application.start()
// Register each controller under its `loco-*` Stimulus identifier. These
// names are required: the components render `data-controller="loco-..."`, so
// registering under any other name means the controller never connects.
application.register("loco-countdown", CountdownController)
application.register("loco-theme", ThemeController)
application.register("loco-alert", AlertController)
application.register("loco-cally-input", CallyInputController)
export { application }
Using Components
Components are rendered like any other Rails ViewComponent, but LocoMotion also
provides ergonomic daisy_* helper methods.
%div
= render(Daisy::Actions::ButtonComponent.new(title: "Click Me"))
%div
= daisy_button(css: "btn-primary") do
Click Me Too
DaisyUI variants are applied by passing DaisyUI classes directly via the css:
option — there are no color: or size: parameters:
= daisy_button(css: "btn-primary btn-lg")
For the full set of available components, parts, slots, and live examples, see the demo site and the API documentation.
Guides
These optional guides cover the broader LocoMotion philosophies and a recommended, opinionated setup for a brand-new Rails project. You do not need them to use the gem — they are published on the demo site:
- Getting Started — Stand up a new Dockerized Rails app with HAML, TailwindCSS, and DaisyUI.
- Docker — A consistent, reliable development environment for any OS.
- HAML — Cleaner, indentation-based templates for a better developer experience.
- Debugging & Testing — Set up RSpec, Playwright, and the remote debugger.
- Service Objects — Structure your business logic with ActiveInteraction.
- Authentication — Wire up OmniAuth sign-in with the developer strategy.
- Error Handling — Inspect errors in the browser with Web Console and BetterErrors.
Documentation & Demo
We expect to settle on and purchase a real domain name in the near future, but for the time being, the latest documentation is available at the links below.
Developing
To work on LocoMotion, first clone the repository and make sure you have Docker installed and running on your machine.
Next, create a .env.local file with the following contents, making sure to
replace the Unsplash keys with real ones (you can create your own account or ask
Topher for his keys).
# .env.local
UNSPLASH_ACCESS_KEY="<< INSERT ACCESS KEY >>"
UNSPLASH_SECRET_KEY="<< INSERT SECRET KEY >>"
You should then be able to run just rebuild in the project directory and then
just all-quick to start the services.
[!NOTE]
We use
yarn linkin thedocs/demo/bin/setupscript to enable quick editing of the Javascript files so you don't have to publish new packages during testing.For the Ruby gem, we point directly to it via the
:pathoption in theGemfile. This means that we have a custom Heroku buildpack when we publish the demo site to move the files into the appropriate places.See https://github.com/profoundry-us/loco_motion-buildpack for more info.
From here, you can access the demo site at http://localhost:3000 and the YARD docs at http://localhost:8808/docs/yard
You can type just demo-shell to open a shell inside the demo Docker container,
or just loco-shell to get a shell inside the gem's Docker container.
See the justfile for all available commands.
[!WARNING]
Right now, Rails doesn't auto-reload the LocoMotion library files when they change, so you might have to restart your server to get it to pickup the changes.
just demo-restart
Contributing
If you're interested in contributing to LocoMotion, please check out our CONTRIBUTING guide which provides detailed information about the contribution process, code standards, documentation requirements, and testing procedures.
Releasing
For core team members who need to release new versions of LocoMotion, please refer to our RELEASING guide for step-by-step instructions on version updates, building, testing, and publishing both the Ruby gem and NPM package.
Tooling
For VSCode, you may want to add the following to your settings to get TailwindCSS Intellisense working properly.
"tailwindCSS.emmetCompletions": true,
"tailwindCSS.includeLanguages": {
"haml": "html",
"ruby": "html",
},
"files.associations": {
"*.html.haml": "haml"
},
"tailwindCSS.experimental.classRegex": [
[ "add_css\\(:[a-z]+, ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
[ "css: ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
[ "class: ?\"([^\"]*)\"", "([a-zA-Z0-9\\-:]+)" ],
[ "(\\.[\\w\\-.]+)[\\n\\=\\{\\s]", "([\\w\\-]+)" ],
],
And because whitespace is important when developing inline components, you
should also add the following which prevents VSCode from adding a newline to the
bottom of your HAML files. This helps ensure that inline components don't have
trailing whitespace when using something like the succeed helper.
"[haml]": {
"editor.formatOnSave": false
}
Alternatively, if your component is simple enough, moving the template inside
the _component.rb file's call method can also alleviate this problem.
So instead of
- # This file has a newline at the bottom which can cause problems
= part(:component) do
= content
you could do something like this:
def call
part(:component) { content }
end
Getting Help
Please reach out by opening an Issue if you've found a bug or starting a Discussion if you have a question!
Please open a Discussion / Issue before starting a Pull Request to make sure we aren't already working on the suggested feature / bug, and to ensure that your solution is aligned with our goals.
TODO / Next Steps
We're actively building out LocoMotion and have made significant progress on the core component library and documentation. Here's what we're working on next:
Completed ✅
- Full component library with DaisyUI wrappers
- Live demo application with all components
- Comprehensive guides (Getting Started, Docker, HAML, Debugging & Testing, Service Objects, Authentication, Error Handling)
- YARD documentation with custom examples
- RSpec test suite
- Playwright E2E tests
- RuboCop configuration
- Docker-based development environment
In Progress 🚧
- Expanding component coverage for remaining DaisyUI components
- Enhancing documentation and examples
- Improving test coverage
Future Plans 📋
- Choose, recommend, and document a pagination gem
- Discuss caching techniques / setup
- Build some docs / guides / examples for using playwright-ruby-client
- See if we can update the Join component to auto-add the
join-itemCSS under certain conditions - Add title and description content_for blocks to all examples for SEO purposes
- Rename the
DockerfiletoDockerfile.locoto be more concise - Make the tooltips documentation button a component and use it for the Labelable concern docs too
If you feel very strongly that you'd like to contribute, please reach out through the GitHub Discussions feature and let us know!