Install
# Gemfilegem 'multitenancy-rails'bundle installGenerate your first theme
bin/rails generate multitenancy storefrontOptional flags:
bin/rails generate multitenancy storefront --tailwindcss --importmapThe generator creates themes/storefront/ with a minimal Rails app structure:
themes/storefront/├── app/│ ├── controllers/application_controller.rb # includes Multitenancy::Controller│ ├── controllers/home_controller.rb│ ├── views/layouts/application.html.erb│ └── views/home/index.html.erb├── config/│ ├── routes.rb│ └── locales/en.ymlSee generator.md for the full list of flags and what they add.
Mount your themes
The gem does not mount themes for you — you decide how they reach the request path.
Path-based
config/routes.rb:
Rails.application.routes.draw do draw(:multitenancy) root 'home#index'endconfig/routes/multitenancy.rb:
Multitenancy.themes.each do |theme| mount theme.engine, at: "/#{theme.name}"endhttp://localhost:3000/storefront → Themes::Storefront::HomeController#index.
Subdomain-based
Multitenancy.themes.each do |theme| constraints subdomain: theme.name do mount theme.engine, at: '/' endendhttp://storefront.lvh.me:3000/ → Themes::Storefront::HomeController#index.
Verify
bin/rails runner 'pp Multitenancy.themes.map(&:name)'# => ["storefront"]
bin/rails serverVisit the mount point — you should see the scaffolded home/index view.
What you get per theme
Each theme is a fully isolated Rails::Engine:
- Namespaced under
Themes::<Name>— classes don’t collide with main app - Its own view path (prepended to the lookup chain)
- Its own route namespace
- Its own
app/assets/andapp/javascript/(if importmap enabled) - Its own locales (
config/locales/en.yml) - Its own RSpec / Minitest / FactoryBot directories (auto-discovered)
What you don’t get automatically:
- Database isolation. Every theme talks to the same database. Scope via
tenant_idcolumns or schemas yourself if you need that. - Request-scoped tenant context. The theme is determined by the mount point, not by runtime lookup. If you need
Current.tenant, add it as abefore_action.
Next steps
- Themes — anatomy of a theme, namespace rules, view resolution quirks
- Integrations — ES modules, Stimulus, Tailwind v4, spec discovery
- API reference