Open-source project
thoughtbot/flutie avatar
thoughtbot/flutie

flutie: Rails view helpers for page titles and body classes

View helpers for Rails applications

731 stars41 forksRubyMIT

At a glance

What is it?
flutie is an MIT licensed Rails gem from thoughtbot that adds two view helpers, one for the page title and one for the body class, both driven by content_for so a page or a controller can override them, and both configurable through an options hash. The judgement is that it is a very small package doing a very specific job, and that the body class helper is the more consequential of the two because it becomes a contract with your stylesheets.
Who is it for?
flutie fits a Rails application whose layouts need a consistent page title and a way to style pages by controller and action, because the two helpers remove a small piece of duplicated layout logic and give you a single place to change the format.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two helpers, and a Railtie to install them

Flutie provides utility view helpers for Rails applications, and the scope is stated in one sentence: there are helpers for setting a page title and for generating body classes.

That is genuinely all it does. The gem is a Railtie, so it is installed the way any Rails engine is, by adding it to the Gemfile:

ruby
gem "flutie"

The supported Ruby and Rails versions are not hard-coded in the readme but taken from the list in the build workflow file in the repository, which is the arrangement to check before you upgrade anything in your application. The gem itself is published with a version badge and a build badge, and the repository carries a gemspec, a Rakefile, a spec directory with an rspec configuration, an Appraisals file and a gemfiles directory, which is the usual layout for a gem that is tested against several versions of its dependencies.

The package is maintained and funded by thoughtbot, with the copyright notice dated 2010, and it is released under the MIT licence. The newest release listed is version 2.2.1 from 2025-06-13, and the last push to the repository was on 2026-04-22.

What follows is the interesting part, and it is short, because the whole design is about where the data comes from.

The page title comes from content_for and the module name

The page title helper is used in the layout like this:

erb
<title><%= page_title %></title>

And by default it produces a title of the form Appname : page title, which is the format most applications want and the format nobody wants to retype in every layout.

The readme explains where each half comes from. The app name comes from the module name of the Rails application, so an application defined as Appname::Application produces Appname, which means the helper does not need a configuration value for the application name at all, it reads it from the constant. The page part comes from trying content_for with the :page_title symbol, which assumes the pages are setting that symbol with content_for. And the separator defaults to a space, a colon and a space.

The important consequence is that the helper is not a title builder with a format string, it is a convention. The layout declares where the title goes, the controller or view declares what the title is, and the helper joins them. A page that does not set content_for at all still produces a sensible title, namely the application name with nothing after it, rather than a blank element or an error.

Three options and a switch that reverses the order

All three parts of the title are overridable per call, through an options hash.

ruby
content_for(:site_page_title, 'My title of my page')
page_title(app_name: 'My app name', page_title_symbol: :site_page_title, separator: " | ")

which produces a title of My app name | My title of my page.

The three keys are app_name, which overrides the module name, page_title_symbol, which changes which content_for key is read, and separator, which changes what sits between the two parts. The middle one is the useful one, because it means a page can set its title under a different key when the application already uses :page_title for something else, or when a section of the site wants its own convention.

There is a fourth option, reverse, which swaps the two parts:

erb
<title>My title of my page : My app name</title>

so with reverse set the page title comes first and the application name second, with the same separator. That exists for the case where the application name reads better as a suffix, which is a common style for a site with a short brand name.

Nothing here is a template engine of its own. The options are plain keyword arguments to a helper method, which means the call sites stay readable and a view can compute the values it passes in.

One detail that is easy to miss, because the readme states it in a sentence rather than a heading, is that the page title and the separator are the defaults, and the override is per call rather than global. There is no configuration file for the separator in the readme, so if you want a different separator in every layout you pass it every time, or you wrap the helper in your own.

The body class is derived from the controller and the action

The second helper is used in the layout in the same way:

erb
<body class="<%= body_class %>">

And it produces a string with the controller name and the controller-action pair, so the show action of a WidgetsController produces:

html
<body class="widgets widgets-show">

Two classes rather than one, and the first is the resource, the second is the resource and the action joined by a hyphen. The names are derived from the controller, so they are plural, and the action is the underscored version.

The helper also has an extension point. Anything added with content_for and the :extra_body_classes key is appended to the end, so a view that sets that content with a value of special-page produces:

html
<body class="widgets widgets-show special-page">

The order matters, and it is fixed. The controller and action classes come first and the view's additions come last, which means a stylesheet can rely on the position of a class in the attribute even though it is not counting on the class list, because the variable part is always at the end. A page that wants to style itself differently can add a class, and a page that wants to be excluded from a rule can use a negation, since the class order is predictable.

The content_for mechanism is the same one the title uses, which is a nice consistency: a view that already sets content_for for a flash message or a section heading now has one more thing it can set, and the layout decides what to do with it.

Why the body class matters more than the title

It is easy to dismiss both helpers as conveniences, and the page title certainly is one. The body class is a different kind of thing, because it becomes an interface.

Once your stylesheets start using the class names that the helper generates, the class names are part of your application's contract. A stylesheet rule for widgets-show will break if the controller is renamed, and a layout that has been rewritten to add a third class will change the order for every page.

That cuts both ways, and it is best to be honest about it. The names are predictable and they are conventional, and they follow the Rails convention that the readme's own example shows, a controller named WidgetsController with a show action producing widgets and widgets-show. A team that adopts the gem is adopting that convention along with the helper, which is a good trade because the convention is the part that would have been written by hand anyway.

The content_for extension point is what makes it more than a naming scheme, because it lets a page add a class that the layout and the stylesheet both agree on without the layout knowing anything about that page. That is the same pattern as the title helper, and it is the pattern that makes the pair of helpers coherent rather than two unrelated conveniences.

The remaining limitation is that neither helper is a view concern in the fuller sense. They do not look at the request, they do not consult the controller beyond its name, and they do not know about locales. For an application whose titles come from a translation framework or from a content management system, the title helper will need to be called with values the application computes itself, and the body helper will need the class list to be the application's own.

A small gem with a long history

The project has been around for a long time by the standards of a two-helper gem, and the repository shows the traces of that.

The copyright notice reads 2010, and the last release listed is 2.2.1 from 2025-06-13. Between those two dates the project has changed hands in the sense that it now lives in the thoughtbot organisation, and the readme carries the standard footer the company adds to its repositories, the note that the names and logos are trademarks of thoughtbot, and links to their other projects and their hiring page.

The repository itself is minimal in the way a small gem should be. There is the gemspec, the lib directory with the code, the spec directory with the tests and the .rspec configuration, an Appraisals file and a gemfiles directory for testing against multiple dependency sets, a Gemfile and a lock file, a Rakefile, a bin directory, a changelog, a contributing document and a security policy.

The security policy is the one file that suggests the project has an owner who thinks about the boring parts, and so does the decision to point the reader at the build workflow for the supported Ruby and Rails versions rather than claiming compatibility in prose. A gem that is a Railtie has to be rebuilt when Rails moves, and pointing at the continuous integration matrix is the honest way to say which combinations are actually tested.

There is no homepage listed for the project and no releases beyond the version numbers on the badge, so the gem is distributed through the usual RubyGems channel and the repository is where you read the source and the contributing guide.

For a package of this size, the maintenance question is a simple one: whether the person who needs a page title that is not the application name still finds the gem small enough to keep.

Editorial conclusion

flutie fits a Rails application whose layouts need a consistent page title and a way to style pages by controller and action, because the two helpers remove a small piece of duplicated layout logic and give you a single place to change the format. It is the wrong choice if your titles come from a CMS or from a translation layer, since the helper only knows about content_for and about the application module name, and it is the wrong choice if you want a richer body class scheme, because the class list is fixed to the controller, the action and whatever the view appends. Before you adopt it, decide which content_for key your pages will use, because the default is page_title and the symbol is configurable per call, and check the supported Ruby and Rails versions in the build workflow, since the gem is a Railtie and has to match your framework.

Frequently asked questions

What is the flutie gem?

It is an MIT licensed Rails gem from thoughtbot that provides utility view helpers for layouts and views: a page_title helper and a body_class helper. It is a Railtie, so it is installed by adding gem "flutie" to the Gemfile.

How does page_title decide the application name?

It comes from the module name of the Rails application, so an application defined as Appname::Application produces Appname. The page part comes from content_for with the :page_title symbol, and the separator defaults to a space, a colon and a space.

Which options does page_title accept?

An options hash with app_name, page_title_symbol and separator, and a reverse option that swaps the two parts. The page_title_symbol key changes which content_for key is read, so a page can set its title under a different symbol.

What does body_class produce?

A string with the controller name and the controller and action pair, so the show action of a WidgetsController produces widgets widgets-show. Anything set with content_for and the :extra_body_classes key is appended at the end.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. thoughtbot/flutie on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/thoughtbot-flutie.svg)](https://hysenlabs.com/projects/thoughtbot-flutie)

Was this useful?