# Rails

Add AdminKit to a Ruby on Rails 8 application with an import map pin for the JavaScript and the stylesheet in the application layout, with Turbo.

Rails 8 uses import maps and Propshaft without a Node build step. The AdminKit script is pinned in the import map and imported in `app/javascript/application.js`; the stylesheet is linked in the application layout.

## Install

```bash
gem install rails
rails new my-app
cd my-app
bin/importmap pin @adminkit/core
```

`bin/importmap pin` downloads `app.js` into `vendor/javascript/` and pins it as `@adminkit/core` in `config/importmap.rb`.

AdminKit PRO is not published to npm. Copy `dist/` from the download into `public/adminkit/` and, instead of the pin and the CDN link below, load `/adminkit/css/app.css` with a `<link>` and `/adminkit/js/app.js` with `<script src="/adminkit/js/app.js" defer data-turbo-track="reload"></script>` in the layout's `<head>`.

## Import the CSS and JavaScript

Import the script in the application's entry point. Turbo Drive replaces `<body>` on every visit while the script keeps running, and `app.js` sets up the icons and the sidebar in each new body.

```js title="app/javascript/application.js"
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import "controllers"
import "@adminkit/core"
```

Import maps only cover JavaScript, so link the stylesheet, which loads its fonts next to it, from the CDN in the `<head>` of the layout (shown in full below), before the Rails tags:

```erb title="app/views/layouts/application.html.erb"
<link href="https://unpkg.com/@adminkit/core/dist/css/app.css" rel="stylesheet" data-turbo-track="reload">
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
```

### Optional: avoid a color mode flash

Without `head.js`, `app.js` applies the stored [color mode](/docs/getting-started/dark-mode/) once it runs, so a visitor who picked the mode opposite to their operating system briefly sees the other one. `head.js` applies it before the first paint. Add it as a plain script before the stylesheet:

```erb
<script src="https://unpkg.com/@adminkit/core/dist/js/head.js"></script>
```

## Minimal layout

```erb title="app/views/layouts/application.html.erb"
<!DOCTYPE html>
<html>
  <head>
    <title><%= content_for(:title) || "Dashboard" %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <link href="https://unpkg.com/@adminkit/core/dist/css/app.css" rel="stylesheet" data-turbo-track="reload">
    <%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>
  </head>

  <body>
    <div class="wrapper">
      <nav id="sidebar" class="sidebar js-sidebar offcanvas-lg offcanvas-start" tabindex="-1" aria-label="Sidebar">
        <div class="sidebar-content js-simplebar">
          <%= link_to root_path, class: "sidebar-brand" do %>
            <span class="align-middle">AdminKit</span>
          <% end %>
          <ul class="sidebar-nav">
            <li class="sidebar-header">Pages</li>
            <li class="sidebar-item <%= 'active' if current_page?(root_path) %>">
              <%= link_to root_path, class: "sidebar-link" do %>
                <i class="align-middle" data-lucide="sliders-vertical"></i> <span class="align-middle">Dashboard</span>
              <% end %>
            </li>
            <li class="sidebar-item <%= 'active' if current_page?("/profile") %>">
              <%= link_to "/profile", class: "sidebar-link" do %>
                <i class="align-middle" data-lucide="user"></i> <span class="align-middle">Profile</span>
              <% end %>
            </li>
          </ul>
        </div>
      </nav>

      <div class="main">
        <nav class="navbar navbar-expand navbar-light navbar-bg">
          <button type="button" class="sidebar-toggle js-sidebar-toggle" aria-controls="sidebar" aria-expanded="true" aria-label="Collapse sidebar">
            <i class="hamburger align-self-center"></i>
          </button>
        </nav>
        <main class="content">
          <div class="container-fluid p-0">
            <%= yield %>
          </div>
        </main>
      </div>
    </div>
  </body>
</html>
```

```ruby title="app/controllers/dashboard_controller.rb"
class DashboardController < ApplicationController
  def index
  end
end
```

```erb title="app/views/dashboard/index.html.erb"
<h1 class="h3 mb-3">Dashboard</h1>
<div class="card">
  <div class="card-body">Hello from AdminKit.</div>
</div>
```

```ruby title="config/routes.rb"
Rails.application.routes.draw do
  root "dashboard#index"
  get "profile", to: "dashboard#profile"
end
```

Add a `profile` action and `app/views/dashboard/profile.html.erb` the same way for the second link.

## Run

```bash
bin/rails server
```

Open http://localhost:3000. You should see the dark sidebar, the navbar with the hamburger toggle and the card. Clicking **Profile** loads the page through Turbo Drive; the icons stay rendered and the toggle keeps working.

## Notes

- The layout above drops the PWA, icon and `yield :head` lines of the generated layout for brevity. Keep them if you need them.
- If you enable a strict content security policy in `config/initializers/content_security_policy.rb`, allow `https://unpkg.com` for `style-src` and `font-src` (and `script-src` for `head.js`).
- The CDN URLs above are unpinned and serve the latest published version. Pin the version `bin/importmap pin` reports, for example `https://unpkg.com/@adminkit/core@<version>/dist/css/app.css`.

---

Canonical HTML page: https://adminkit.io/docs/frameworks/rails/

Site overview for agents: https://adminkit.io/llms.txt (expanded: https://adminkit.io/llms-full.txt) · Documentation: https://adminkit.io/docs/ · Questions: support@adminkit.io
