A demonstration repository showing two different approaches for integrating Tailwind CSS with Rails engines.
This repository contains two example Rails engines that demonstrate different strategies for using Tailwind CSS:
- blogh_isolate - Isolated Tailwind build approach
- blogh_main_app_layout - Shared Tailwind build approach
Each approach has its own trade-offs and is suitable for different use cases.
The engine maintains its own Tailwind CSS build system, completely independent of the host application.
- Engine has its own Tailwind build process
- Uses the
tailwindcss-railsgem as a dependency - Provides its own layout with isolated styles
- Auto-builds Tailwind CSS in development mode
- Includes Rake tasks for building and watching CSS
blogh_isolate/
├── app/
│ ├── assets/
│ │ ├── builds/blogh/
│ │ │ └── tailwind.css # Compiled output
│ │ ├── tailwind/blogh/
│ │ │ └── application.css # @import "tailwindcss"
│ │ └── stylesheets/blogh/
│ │ └── application.css # @import url("tailwind.css")
│ └── views/
│ ├── layouts/blogh/
│ │ └── application.html.erb # Engine's own layout
│ └── blogh/home/
│ └── index.html.erb # Uses Tailwind classes
├── lib/
│ ├── blogh/
│ │ └── engine.rb # Auto-builds in development
│ └── tasks/
│ └── blogh_tasks.rake # Build & watch tasks
└── blogh.gemspec # Includes tailwindcss-rails
1. Gemspec Configuration (blogh.gemspec)
spec.add_dependency "rails", ">= 8.1.1"
spec.add_dependency "tailwindcss-rails"2. Engine Configuration (lib/blogh/engine.rb)
module Blogh
class Engine < ::Rails::Engine
isolate_namespace Blogh
initializer 'blogh.tailwindcss', before: :load_config_initializers do
if Rails.env.development?
Rails.application.config.after_initialize do
begin
require 'rake'
require 'tailwindcss-rails'
Rails.application.load_tasks
Rake::Task['blogh:tailwindcss:build'].invoke
rescue LoadError => e
Rails.logger.warn "Blogh: Could not load tailwindcss-rails: #{e.message}"
rescue StandardError => e
Rails.logger.warn "Blogh: Failed to build Tailwind CSS: #{e.message}"
end
end
end
end
end
end3. Tailwind Input (app/assets/tailwind/blogh/application.css)
@import "tailwindcss";4. Stylesheet Manifest (app/assets/stylesheets/blogh/application.css)
@import url("tailwind.css");5. Layout (app/views/layouts/blogh/application.html.erb)
<!DOCTYPE html>
<html>
<head>
<title>Blogh</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "blogh/application", media: "all" %>
</head>
<body>
<%= yield %>
</body>
</html>6. Rake Tasks (lib/tasks/blogh_tasks.rake)
The engine includes custom Rake tasks for building and watching Tailwind CSS:
# Build once
rake blogh:tailwindcss:build
# Watch for changes
rake blogh:tailwindcss:watch- Complete isolation - engine styles won't conflict with host app
- Engine can be used standalone or in multiple applications
- Full control over Tailwind configuration and build process
- Works even if host application doesn't use Tailwind
- Adds
tailwindcss-railsas a dependency - Requires separate build process
- Larger overall CSS bundle if host app also uses Tailwind
- More complex setup and maintenance
- Engine needs to work in applications without Tailwind
- Engine requires specific Tailwind configuration
- Complete style isolation is critical
- Engine is distributed as a standalone gem
The engine integrates with the host application's Tailwind build by adding its content paths to the main app's configuration.
- Uses the host application's Tailwind build
- No additional dependencies required
- Relies on host app's layout
- Minimal setup required
- Lighter weight approach
blogh_main_app_layout/
├── app/
│ └── assets/
│ └── stylesheets/blogh/
│ └── application.css # Can be empty or minimal
├── lib/
│ └── blogh/
│ └── engine.rb # Adds content paths
└── blogh.gemspec # No tailwindcss-rails dependency
1. Gemspec Configuration (blogh.gemspec)
spec.add_dependency "rails", ">= 8.1.1"
# Note: No tailwindcss-rails dependency2. Engine Configuration (lib/blogh/engine.rb)
module Blogh
class Engine < ::Rails::Engine
isolate_namespace Blogh
initializer "blogh.tailwind" do |app|
app.config.tailwind_content_paths ||= []
app.config.tailwind_content_paths += [
root.join("app/views/**/*.{erb,slim}").to_s,
root.join("app/components/**/*.rb").to_s,
root.join("app/helpers/**/*.rb").to_s,
root.join("app/javascript/**/*.js").to_s
]
end
end
end3. Host Application Setup
The host application must:
- Have Tailwind CSS configured (e.g., via
tailwindcss-rails) - Include the engine styles in the layout
- Use the main application layout for engine views
- Minimal setup required
- No additional dependencies
- Single Tailwind build for entire application
- Smaller overall CSS bundle
- Automatically shares design system with host app
- Requires host application to use Tailwind CSS
- Engine cannot be used standalone
- Less control over styling
- Potential for style conflicts with host app
- Building an engine for a specific application
- Host application already uses Tailwind CSS
- Want to share design system between engine and host app
- Prefer minimal dependencies and simple setup
- Engine won't be distributed as a standalone gem
| Feature | Isolated Build | Shared Build |
|---|---|---|
| Dependencies | Requires tailwindcss-rails |
No additional deps |
| Setup Complexity | More complex | Minimal |
| Build Process | Separate engine build | Uses host app build |
| Style Isolation | Complete isolation | Shares with host app |
| Standalone Usage | Yes | No |
| Host App Requirements | None | Must use Tailwind |
| CSS Bundle Size | Larger (if host uses Tailwind) | Smaller |
| Maintenance | More overhead | Less overhead |
- Ruby 3.x
- Rails 8.1.1+
- Node.js (for Tailwind CSS)
cd blogh_isolate
bundle install
# Build Tailwind CSS
bundle exec rake blogh:tailwindcss:build
# Run the test application
cd test/dummy
bin/rails server
# Visit http://localhost:3000cd blogh_main_app_layout
bundle install
# The host application must have Tailwind CSS configured
cd test/dummy
bin/rails server
# Visit http://localhost:3000- You're building a gem for public distribution
- The engine needs to work in various applications
- You require specific Tailwind configuration
- Complete style isolation is essential
- Building an engine for a specific application
- The host app already uses Tailwind CSS
- You want to minimize dependencies
- Sharing the design system is beneficial
MIT