twitter-bootstrap-rails Documentation

Twitter Bootstrap for Rails 8

4,463 stars HTML HTML 1 file Β· ~4,642 tokens #bootstrap#bootstrap-generator#rails-gem#twitter-bootstrap-rails
RAW Doc

Technical Documentation: seyhunak/twitter-bootstrap-rails

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)

twitter-bootstrap-rails




Integrates Bootstrap 5.3.8 into Rails Asset Pipeline. Supports Rails 8, 7, 6, 5.

Install

ruby
# Gemfile
gem "twitter-bootstrap-rails"
bash
bundle install
rails generate bootstrap:install static

Generators

Every code snippet on the
Bootstrap 5.3 Introduction page
is reproducible from a command:

Docs snippet Command
Starter template rails g bootstrap:starter
CDN CSS <link> rails g bootstrap:cdn --css
CDN JS bundle <script> rails g bootstrap:cdn --js
Popper + bootstrap.js separately rails g bootstrap:cdn --separate-popper
Important globals (doctype, lang, viewport) baked into every generated layout and the starter template
bash
# Install Bootstrap assets into the asset pipeline
rails g bootstrap:install static

# ...or load Bootstrap from the jsDelivr CDN instead
rails g bootstrap:install cdn

# Generate a Bootstrap layout
rails g bootstrap:layout application

# ...linking Bootstrap from the CDN, with Subresource Integrity
rails g bootstrap:layout application --cdn

# ...using Popper and bootstrap.js separately rather than the bundle
rails g bootstrap:layout application --cdn --separate-popper

# Write the starter template from the Bootstrap docs
rails g bootstrap:starter                    # -> public/bootstrap-starter.html
rails g bootstrap:starter --path=public/demo.html

# Print CDN tags to paste into a layout you already own (writes nothing)
rails g bootstrap:cdn

# Generate themed views for scaffold
rails g scaffold Task title:string done:boolean
rails db:migrate
rails g bootstrap:themed Tasks

bootstrap:install cdn records the choice in config/initializers/bootstrap.rb,
so bootstrap:layout emits CDN tags by default afterwards. Pass --cdn or
--no-cdn to override it per run.

Both asset pipelines are supported. On Sprockets, static adds require
directives to your manifests. On Propshaft (the Rails 8 default) there are no
directives to add, so the generated layout links the vendored files directly β€”
run rails g bootstrap:layout after bootstrap:install static either way.

The Bootstrap version and its CDN URLs and integrity hashes live in one place,
Twitter::Bootstrap::Rails::BOOTSTRAP_CDN. No template hardcodes them.

Snippets

Every snippet published at
getbootstrap.com/docs/5.3/examples
β€” 62 of them across 12 categories β€” is a command. Each writes an .html.erb
partial into app/views/shared/:

bash
rails g bootstrap:header               # the first variant, "centered"
rails g bootstrap:header dark_search   # a specific variant
rails g bootstrap:header --list        # what's available, with descriptions
Command Variants
rails g bootstrap:header centered, nav_pills, with_auth_buttons, dark_search, light_search, grid_dropdown, double, dark_double
rails g bootstrap:hero centered, centered_screenshot, with_image, signup_form, cropped_image, dark
rails g bootstrap:features columns_with_icons, hanging_icons, custom_cards, icon_grid, with_title
rails g bootstrap:sidebar dark, light, icon_only, collapsible, list_group
rails g bootstrap:footer simple, with_brand, with_nav, columns, with_newsletter
rails g bootstrap:dropdown simple, with_search, with_icons, calendar, mega_menu
rails g bootstrap:list_group with_avatars, checkboxes, checkboxes_expanded, checkable, radios
rails g bootstrap:modal sheet, confirm, whats_new, signup
rails g bootstrap:badge pills, subtle, subtle_bordered, with_avatar, with_icons, with_avatar_divider
rails g bootstrap:breadcrumb basic, with_icons, chevron, custom
rails g bootstrap:button pills, grid, with_icons, loading, circle
rails g bootstrap:jumbotron with_icon, placeholder, full_width, basic

Variants are listed in the order they appear on the docs page, so the first one
in each row is the first example Bootstrap shows.

Options, on every snippet command:

Option Effect
--list Print the variants with descriptions and exit, writing nothing
--as=NAME Partial name to write (default: the generator name)
--path=DIR Where to write it (default: app/views/shared)
--no-icons Skip installing the shared icon sprite
bash
rails g bootstrap:footer columns --as=site_footer --path=app/views/layouts
# -> app/views/layouts/_site_footer.html.erb

Placeholder images

Five snippets (hero centered, hero centered_screenshot, hero with_image,
hero cropped_image, features custom_cards) reference placeholder images that
only exist on Bootstrap's docs site, so they 404 until you point them at your own
assets. The generator warns you when you pick one.

Icons

36 of the 62 snippets use Bootstrap Icons through an SVG sprite. Those commands
also write _bootstrap_icons.html.erb next to the partial. Render it once,
near the top of `` in your layout, or those icons come out as empty boxes:

erb
<%= render "shared/bootstrap_icons" %>

Quick Start

bash
rails new myapp
cd myapp
echo 'gem "twitter-bootstrap-rails"' >> Gemfile
bundle install
rails generate bootstrap:install static
rails generate scaffold Task title:string description:text completed:boolean
rails db:migrate
rails generate bootstrap:themed Tasks
rails generate bootstrap:layout application
rails server

Run bootstrap:layout even if you already have a layout β€” that step is what puts
Bootstrap's CSS and JS on the page.

Upgrading to 5.4.0

5.4.0 is a breaking release:

  • Less is gone. rails g bootstrap:install less no longer exists; the
    argument is now static (default) or cdn. Bootstrap 5 has no Less build, and
    the less-rails and execjs dependencies have been dropped.
  • Glyphicons are gone, including the glyph helper. Bootstrap dropped them in
    v4. The snippet generators ship Bootstrap Icons instead.
  • CoffeeScript support is gone, along with --no-coffeescript.
  • The gem version no longer tracks the Bootstrap version.
    Twitter::Bootstrap::Rails::BOOTSTRAP_VERSION says which Bootstrap ships.

If you are on Rails 8, note that bootstrap:install static previously left
Propshaft apps with no Bootstrap at all β€” that is fixed here. See the
CHANGELOG for the full list.


Buy me a Coffee

β˜• Support the Project

Contributors

Thanks to all contributors who are helping to make better.

Star History

License

MIT. Copyright (c) 2025 (since 2011) by Seyhun AkyΓΌrek


Superpowers Specs 2026 08 02 Bootstrap 53 Generators Design (`docs/superpowers/specs/2026-08-02-bootstrap-53-generators-design.md`)

Bootstrap 5.3.8 adaptation and Introduction-page snippet generators

Date: 2026-08-02
Status: Approved

Goal

Bring twitter-bootstrap-rails up to Bootstrap 5.3.8, and make every code snippet
on https://getbootstrap.com/docs/5.3/getting-started/introduction/ reproducible
through a rails g bootstrap:* command.

Background

The gem is currently inconsistent and partly broken:

  • app/assets/stylesheets/twitter-bootstrap-static/bootstrap.css vendors Bootstrap
    5.3.3; the generated layout CDN-pins 5.3.3 separately. Two places to bump.

  • InstallGenerator#copy_bootstrap_assets globs
    vendor/assets/stylesheets/twitter/bootstrap and
    vendor/assets/javascripts/twitter/bootstrap. Neither path exists. Dir.glob
    returns [], so the method creates two empty directories in the host app and
    copies nothing, silently.

    Correction (verified during implementation): both paths exist and are
    git-tracked, holding Bootstrap 5.3.3. The glob works. The real defects in this
    area turned out to be:

    • vendor/assets/stylesheets/twitter-bootstrap-static/bootstrap.css.erb is
      Bootstrap 3.1.1 and occupies the same logical asset path as the Bootstrap 5
      app/assets/stylesheets/twitter-bootstrap-static/bootstrap.css that
      bootstrap_and_overrides.css requires. Whichever the pipeline resolves first wins.
    • add_assets calls File.exist? on paths relative to the working directory
      rather than the destination root, so an existing application.js /
      application.css is never detected and gets overwritten by the gem's template.
    • On Propshaft apps there is no require_self anchor, so the require insertion
      silently does nothing.
  • vendor/toolkit/**/*.less and vendor/static-source/*.less are the Bootstrap 3
    Less source. Bootstrap 5 has no Less build. The gemspec still hard-depends on
    less-rails ~> 4.0 and execjs ~> 2.7, and ships a post_install_message telling
    users to install a JavaScript runtime for Less compilation.

  • app/assets/fonts/glyphicons-halflings-regular.* and app/helpers/glyph_helper.rb
    support Glyphicons, which Bootstrap dropped in v4.

Scope

In scope: the five snippets on the Introduction page only.

  1. CDN CSS <link>
  2. CDN JS bundle <script>
  3. The starter HTML template
  4. Popper + bootstrap.js as separate <script> tags
  5. "Important globals" β€” HTML5 doctype, <html lang>, viewport meta

Out of scope: component snippets from the rest of the Bootstrap docs (alerts, cards,
modals, ...). Those may become partials in a later pass.

Design

1. Single source of truth for upstream coordinates

lib/twitter/bootstrap/rails/version.rb carries the Bootstrap version and the CDN
URLs with their integrity hashes. No template hardcodes either.

ruby
module Twitter
  module Bootstrap
    module Rails
      VERSION = "5.4.0"
      BOOTSTRAP_VERSION = "5.3.8"
      POPPER_VERSION = "2.11.8"

      BOOTSTRAP_CDN = {
        css: {
          url: "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css",
          integrity: "sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
        },
        bundle: {
          url: "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js",
          integrity: "sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
        },
        js: {
          url: "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js",
          integrity: "sha384-G/EV+4j2dNv+tEPo3++6LCgdCROaejBqfUeNjuKAiuXbjrxilcCdDz6ZAVfHWe1Y"
        },
        popper: {
          url: "https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js",
          integrity: "sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
        }
      }.freeze
    end
  end
end

Bumping Bootstrap becomes a one-file change plus re-vendoring the two dist files.

A shared module Bootstrap::Generators::CdnTags renders tag strings from this hash
and is mixed into the generators that need them. It exposes css_tag,
bundle_tag, popper_tag, and js_tag, each returning the exact markup from the
docs page.

2. Snippet-to-command mapping

Docs snippet Command
Starter template rails g bootstrap:starter
Important globals baked into every layout and starter template
CDN CSS link rails g bootstrap:layout --cdn
CDN JS bundle rails g bootstrap:layout --cdn
Popper + bootstrap.js separately rails g bootstrap:layout --cdn --separate-popper
Any of the above, as text rails g bootstrap:cdn

3. `bootstrap:install`

Signature: rails g bootstrap:install [static|cdn], default static.

  • static (default) vendors Bootstrap 5.3.8 into the host app's asset pipeline and
    adds the require lines to the CSS/JS manifests.
  • cdn skips vendoring entirely and writes config/initializers/bootstrap.rb
    containing Twitter::Bootstrap::Rails.asset_mode = :cdn. bootstrap:layout reads
    Twitter::Bootstrap::Rails.asset_mode to pick its default; passing --cdn or
    --no-cdn overrides it. The accessor is defined in
    lib/twitter/bootstrap/rails/bootstrap.rb as an mattr_accessor defaulting to
    :static, so the layout generator works whether or not the initializer exists.

Behaviour changes:

  • copy_bootstrap_assets is fixed to read from paths that exist. Bootstrap 5.3.8's
    bootstrap.min.css and bootstrap.bundle.min.js are downloaded from jsDelivr,
    verified against the integrity hashes above, and committed to
    vendor/assets/stylesheets/twitter-bootstrap-static/ and
    vendor/assets/javascripts/twitter/bootstrap/ respectively. The generator raises
    a clear error if a source file is missing rather than creating empty directories.
  • The less argument value, the bootstrap_and_overrides.less template, the
    --no-coffeescript option, and the bootstrap.coffee template are removed.

4. `bootstrap:layout`

Gains two options:

  • --cdn / --no-cdn β€” emit the jsDelivr <link>/<script> tags with integrity
    and crossorigin attributes, instead of stylesheet_link_tag /
    javascript_include_tag. Default comes from the mode recorded by
    bootstrap:install, falling back to vendored.
  • --separate-popper β€” with --cdn, emit the Popper + bootstrap.min.js pair
    instead of the single bundle. Ignored with a warning when --cdn is not set,
    since the vendored path ships the bundle.

All three template engines (erb, haml, slim) support both options.

5. `bootstrap:starter` (new)

Writes the Introduction page's starter template to public/bootstrap-starter.html
β€” a standalone HTML document with no ERB, so public/ is where it can be opened
directly in a browser. --path=PATH overrides the destination. The file is the docs
snippet verbatim, with the version and integrity values interpolated from the
constants.

6. `bootstrap:cdn` (new)

Prints tags to stdout rather than writing a file, for pasting into a layout the user
already owns. Writes nothing to disk.

  • rails g bootstrap:cdn β€” CSS link + JS bundle script
  • rails g bootstrap:cdn --css β€” CSS link only
  • rails g bootstrap:cdn --js β€” JS bundle script only
  • rails g bootstrap:cdn --separate-popper β€” Popper + bootstrap.js pair

7. Removals

Deleted outright, since nothing in Bootstrap 5 uses them:

  • vendor/toolkit/ (Bootstrap 3 Less source)
  • vendor/static-source/ (Bootstrap 3 Less source)
  • app/assets/fonts/glyphicons-halflings-regular.*
  • app/helpers/glyph_helper.rb and spec/lib/twitter_bootstrap_rails/glyph_helper_spec.rb
  • lib/generators/bootstrap/install/templates/bootstrap_and_overrides.less
  • lib/generators/bootstrap/install/templates/bootstrap.coffee
  • gemspec: the less-rails and execjs dependencies, and post_install_message

GlyphHelper is removed rather than deprecated because its icon font is being
deleted in the same pass; leaving the helper would emit markup for glyphs that no
longer resolve.

Versioning

Gem version goes to 5.4.0. Dropping Less, Glyphicons, and the less install
argument breaks existing users, so this cannot be a patch. The gem version
consequently stops tracking the Bootstrap version; BOOTSTRAP_VERSION is the
authoritative statement of which Bootstrap ships.

Testing

New specs under spec/lib/generators/, using Rails::Generators::TestCase against
a tmp destination root:

  • install_generator_spec β€” static vendors both dist files into the destination
    and inserts the manifest require lines; cdn vendors nothing and writes the
    initializer; a missing vendored source raises rather than silently no-opping.
  • layout_generator_spec β€” default emits stylesheet_link_tag; --cdn emits the
    CSS link and bundle script with the exact URL and integrity from the constants;
    --cdn --separate-popper emits the Popper and bootstrap.min.js pair and no
    bundle; --separate-popper without --cdn warns. Repeated per engine.
  • starter_generator_spec β€” output is byte-identical to the docs snippet once the
    version and hashes are interpolated; --path is honoured.
  • cdn_generator_spec β€” each flag prints the expected tags and writes no file.
  • A guard spec asserting no template contains a hardcoded bootstrap@ version
    string, so the constants stay the only source.

Existing helper specs continue to run unchanged, minus the deleted glyph spec.

Documentation

README: update the generator table with bootstrap:starter and bootstrap:cdn and
the new bootstrap:layout options. CHANGELOG: a 5.4.0 entry with a Breaking Changes
section covering the Less, Glyphicons, coffeescript, and bootstrap:install less
removals, and the fixed vendoring bug.


--- METRICS ---