This guide walks you through standing up a brand-new Rails application using the philosophies and tooling that LocoMotion recommends: Docker for a stable development environment, Just for command running, HAML for templates, and TailwindCSS + DaisyUI for styling.
You do not need to follow this guide to use the LocoMotion gem — see the Install guide for adding the component library to an existing app. This guide presents an opinionated starting point for new projects, but you should feel free to adapt these recommendations to suit your preferences and requirements.
We recommend using Docker from the very beginning — even before you run
rails new. This gives you a stable development environment regardless of
your OS, and keeps the dev container small and simple so troubleshooting
is easy.
For the full Docker walkthrough — installing Docker, copying the example
config files, and booting the containers — follow the
Docker guide first. Once you can run
just dev to build the containers and just dev-shell to open a shell
inside the development container, come back here.
We use Just as our command runner instead of Make. It provides a cleaner, more readable syntax for defining commands, better error handling, and is easier to maintain than complex Makefiles.
Inside the development container, everything is set up and ready for you
to install Rails. Change into the app directory (which is mapped to your
local machine) and run rails new:
cd /home/app && rails new . --skip --database=postgresql --javascript=esbuild --css=tailwind
If you want something other than PostgreSQL or TailwindCSS, you can change
that here — these are just our recommendations.
We also tend to recommend lagging slightly behind the latest Ruby version,
as the newest release occasionally has trouble building the Rails project.
You can change it in dev/Dockerfile via the FROM line at the top.
If you run into trouble with the rails new command, this resets the
generated files so you can try again without losing your dev config:
rm -rf .dockerignore .git .gitattributes .gitignore .node-version .ruby-version Gemfile README.md Rakefile app bin config config.ruOpen the newly created config/database.yml and add the following three
lines under the default key so Rails can reach the Postgres container:
# Under the default section in config/database.yml
host: db
username: postgres
password: passwordNow uncomment the app section in your docker-compose.yml file and run
just app to build and start the application. After a minute or two you
should see Puma listening on port 3000, and you can visit
http://localhost:3000 to view your running app!
Once the container is built, you can run just app-fast to simply start
the containers without rebuilding. This is much faster than a full
build every time.
We believe strongly in using UUIDs for primary keys to increase security and avoid potential scaling issues down the road. To enable this by default for all generated models, create the following initializer:
# config/initializers/generators.rb
Rails.application.config.generators do |generator|
generator.orm :active_record, primary_key_type: :uuid
endWhile you can use the default ERB templating system, we highly recommend
HAML — it provides a much cleaner language for your
template files. Add the gems to your Gemfile:
# App-Specific Gems
gem "haml-rails", "~> 2.0"
# For development only (helps convert ERB to HAML)
group :development do
gem "html2haml"
endOpen a Docker shell in the app container with just app-shell and run
bundle to install the gems. Then point Tailwind at your HAML views by
updating tailwind.config.js:
module.exports = {
content: [
'./app/views/**/*.html.haml',
// ...
]
}Finally, convert any existing .erb files to .haml:
This deletes your ERB files, so make sure you have a backup or can easily
do a git revert.
HAML_RAILS_DELETE_ERB=true rails haml:erb2haml
For a deeper dive into HAML syntax and conventions, see the HAML guide.
TailwindCSS is a utility-based CSS framework
that lets you build components by composing utility classes. It is already
installed via the rails new command above, and we highly recommend it
for every project.
DaisyUI builds on top of Tailwind by providing
ready-made component classes, so a button becomes as simple as
%button.btn. With Tailwind 4, DaisyUI is configured directly in your CSS
file rather than in tailwind.config.js. Open an app shell with
just app-shell and install the packages:
yarn add tailwindcss @tailwindcss/cli daisyui
Then add the @import and @plugin directives to your
application.tailwind.css:
/* Import the base Tailwind theme */
@import 'tailwindcss';
/* Include DaisyUI via @plugin directive */
@plugin 'daisyui' {
themes: light --default, dark --prefersdark;
}
/* Custom variant to reduce selector specificity for component defaults */
@custom-variant where (:where(&));
/* Custom dark: variant for System-based & DaisyUI ThemeController dark mode */
@custom-variant dark (@media (prefers-color-scheme: dark), :root:has(input.theme-controller[value=dark]:checked) &);
/* Point to tailwind.config.js for content scan paths only */
@config "../tailwind.config.js";Tailwind 4 moves all plugin configuration into the CSS file. Do not
add DaisyUI to tailwind.config.js — that file is now only used to
declare content scan paths.
LocoMotion lets you attach a tooltip to many components with the tip:
attribute, which adds the tooltip class and data-tip directly to the
element. DaisyUI 5, however, only reveals a tooltip on keyboard focus when
the focused element is a child of the .tooltip element — so tooltips
placed directly on a focusable element (a button, link, etc.) show on hover
but not when a keyboard user tabs to them.
Add this small rule to your application.tailwind.css so those tooltips
also appear on focus. It mirrors DaisyUI's own reveal rule for the case
where the tooltip element itself is focused:
/* Reveal `tip:`/`tooltip` tooltips on keyboard focus */
.tooltip:focus-visible:is([data-tip]:not([data-tip=""]), :has(.tooltip-content:not(:empty))) {
&[data-tip]::before,
&::after,
& > .tooltip-content {
opacity: 1;
--tt-pos: 0rem;
}
}If you'd rather not add custom CSS, wrap the element in the
daisy_tooltip (aliased daisy_tip) component instead. That follows
DaisyUI's recommended structure — the focusable element becomes a child of
the .tooltip, so focus works without any extra rule.
With everything installed, let's confirm it all works. First, tell the
Rails server to bind to all interfaces in your Procfile.dev:
web: env RUBY_DEBUG_OPEN=true bin/rails server -b 0.0.0.0Update your Dockerfile to start the app using Foreman:
# Change this line:
CMD ["rails", "server", "-b", "0.0.0.0"]
# To this:
CMD ["./bin/dev"]Since we are using Docker, it also helps to clear out stale PID files on
boot. Add these lines to bin/setup, just above the lines that restart
the application server:
puts "\n== Removing old PID files =="
system! "rm -rf /home/app/tmp/pids/server.pid"Restart with just app (a full rebuild is required because we changed the
Dockerfile). Now wire up a quick test route and controller action:
# config/routes.rb
root "application#test"
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def test
render html: "Test", layout: true
end
endAnd modify your layout's body to show some Tailwind styling (and, if you installed it, a DaisyUI button):
- # app/views/layouts/application.html.haml
%body
.m-2.p-2.rounded.bg-red-400
= yield
- # If you installed DaisyUI, add this too:
.btn
Test ButtonVisit http://localhost:3000 — you should see a red, rounded box with the word "Test", and a gray DaisyUI button that reacts when you hover and click it!
Once you are done playing around, undo these layout and routing changes so they do not cause confusion later.
You now have a fully-configured Rails app the LocoMotion way. From here, set up a solid foundation with the Debugging & Testing guide, structure your business logic with the Service Objects guide, and add user sign-in with the Authentication guide.
Create virtual credit / debit cards to keep your real info safe.
Get $5 when you sign up — free to start!
Everything you need to grow your business with confidence!
CRM, Lead Generation, Project Management, Contracts, Online Payments, and more!
The ads above are affiliate links to products I regularly use and highly
recommend.
I may receive a commission if you decide to purchase.