# Devise Part 3: Updating Our Devise Views With Tailwind CSS

> In part three of the series, we walk through how to add TailwindCSS to a Rails 7 project and spruce up our sign in page.

- Canonical: https://dennisokeeffe.com/blog/2022-03-07-part-3-updating-our-devise-views-with-tailwind-css
- Published: 2022-03-07
- Updated: 2022-03-07
- Tags: ruby, ruby-on-rails, devise

In the [previous post (part two)](https://blog.dennisokeeffe.com/blog/2022-03-07-part-2-using-redis-sessions-instead-of-cookie-store), we changed our Devise setup to use Redis for sessions. This will be required going forward (but feel free to swap back to the cookie store).

Today, we will take a quick pivot to beautify our sign in page using [TailwindCSS](https://tailwindcss.com/) and [TailwindUI](https://tailwindui.com/).

We are going to specifically implement the demo [sign in](https://tailwindui.com/components/application-ui/forms/sign-in-forms) component that comes for free.

Source code can be found [here](https://github.com/okeeffed/demo-rails-7-with-devise-series).

## Prerequisites

1. Basic familiarity with setting up a [new Rails project](https://guides.rubyonrails.org/getting_started.html).
2. Some familiarity with [TailwindCSS](https://tailwindcss.com/) would be useful as we won't really cover how it works.

## Getting started

We will be working from the source code found [here](https://github.com/okeeffed/demo-rails-7-with-devise-series).

```s
# Clone and change into the project
$ git clone https://github.com/okeeffed/demo-rails-7-with-devise-series
$ cd demo-rails-7-with-devise-series

# Continue from part 2 - warning that Redis required
$ git checkout 2-using-redis-sessions

# Add required gems and setup the files
$ bundler add tailwindcss-rails
$ bin/rails tailwindcss:install

# We want to update our Devise views, so we will need to scaffold them
$ bin/rails generate devise:views
```

Note that since we want to update our Devise views, we will need to scaffold them. This is done in the last command of the above.

The `bin/rails tailwindcss:install` went ahead and added a `bin/dev` file and updated our `Procfile.dev` to run a command to watch TailwindCSS.

To see the fruits of our labor, start the server with `bin/dev` (instead of `bin/rails s`).

## Updating our Devise views

I went ahead and did a lot of the work for our Devise view here in converting over the [desired component](https://tailwindui.com/components/application-ui/forms/sign-in-forms) to ERB.

Update `app/views/devise/sessions/new.html.erb` to the following:

```html
<div
  class="min-h-full flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8"
>
  <div class="max-w-md w-full space-y-8">
    <div>
      <img
        class="mx-auto h-12 w-auto"
        src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"
        alt="Workflow"
      />
      <h2 class="mt-6 text-center text-3xl font-extrabold text-gray-900">
        Sign in to your account
      </h2>
      <%- if devise_mapping.registerable? && controller_name != 'registrations'
      %>
      <p class="mt-2 text-center text-sm text-gray-600">
        Or <%= link_to "sign up", new_registration_path(resource_name), class:
        "font-medium text-indigo-600 hover:text-indigo-500" %>
      </p>
      <% end %>
    </div>
    <%= form_for(resource, as: resource_name, url: session_path(resource_name),
    html: { data: { turbo: false} }) do |f| %>
    <div class="mt-8 space-y-6">
      <input type="hidden" name="remember" value="true" />
      <div class="rounded-md shadow-sm -space-y-px">
        <div>
          <%= f.label :email, class: "sr-only", for: "email-address" %> <%=
          f.email_field :email, id: "email-address", autofocus: true,
          autocomplete: "email", placeholder: "Email address", class:
          "appearance-none rounded-none relative block w-full px-3 py-2 border
          border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md
          focus:outline-none focus:ring-indigo-500 focus:border-indigo-500
          focus:z-10 sm:text-sm" %>
        </div>
        <div>
          <%= f.label :password, for: "password", class: "sr-only" %> <%=
          f.password_field :password, id: "password", autocomplete:
          "current-password", placeholder: "Password", class: "appearance-none
          rounded-none relative block w-full px-3 py-2 border border-gray-300
          placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none
          focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
          %>
        </div>
      </div>
      <% if devise_mapping.rememberable? %>
      <div class="flex items-center justify-between">
        <div class="field flex items-center">
          <%= f.check_box :remember_me, class: "h-4 w-4 text-indigo-600
          focus:ring-indigo-500 border-gray-300 rounded" %> <%= f.label
          :remember_me, class: "ml-2 block text-sm text-gray-900" %>
        </div>
        <div class="text-sm">
          <%- if devise_mapping.recoverable? && controller_name != 'passwords'
          && controller_name != 'registrations' %> <%= link_to "Forgot your
          password?", new_password_path(resource_name), class: "font-medium
          text-indigo-600 hover:text-indigo-500" %> <% end %>
        </div>
      </div>
      <% end %>
      <div class="actions">
        <%= f.submit "Log in", class: "actions group relative w-full flex
        justify-center py-2 px-4 border border-transparent text-sm font-medium
        rounded-md text-white bg-indigo-600 hover:bg-indigo-700
        focus:outline-none focus:ring-2 focus:ring-offset-2
        focus:ring-indigo-500" %>
      </div>
    </div>
    <% end %>
  </div>
</div>
```

You will also need to update the `app/views/layouts/application.html.erb` view to remove all the classes from `main`:

```html
<!doctype html>
<html>
  <head>
    <title>DemoRails7WithDeviseSeries</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag
    "tailwind", "inter-font", "data-turbo-track": "reload" %> <%=
    stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%=
    javascript_importmap_tags %>
  </head>
  <body>
    <main><%= yield %></main>
  </body>
</html>
```

If you now refresh the page, we will have a lovely component in place of what we had before!

![Before](https://cdn.dennisokeeffe.com/assets/2022-03-07-part-3-updating-our-devise-views-with-tailwind-css/1-sign-in.webp)

...and after:

![After](https://cdn.dennisokeeffe.com/assets/2022-03-07-part-3-updating-our-devise-views-with-tailwind-css/2-after.webp)

Go through the normal flow of sign-in to confirm that it all works as expected from the previous parts.

## Summary

In this part, we detoured to add in Tailwind CSS and make our sign in page look a little livelier.

Although we do not cover it, you could take this further by beautifying the other sign up page that we have (you'll notice it still looks crummy) but I won't be doing that here as we can confirm that Tailwind is up and working.

## Resources and further reading

- [Rails getting started](https://guides.rubyonrails.org/getting_started.html)
- [Source code](https://github.com/okeeffed/demo-rails-7-with-devise-series)
- [TailwindCSS](https://tailwindcss.com/)
- [TailwindUI](https://tailwindui.com/)
- [Series: Devise with Ruby on Rails 7](https://blog.dennisokeeffe.com/blog/series/devise-with-ruby-on-rails-7)
- [Devise Part 1: Setting Up Devise With Rails 7 And React](https://blog.dennisokeeffe.com/blog/2022-03-07-part-1-setting-up-devise-with-rails-7)
- [Devise Part 2: Using Redis Sessions Instead Of The Cookie Store](https://blog.dennisokeeffe.com/blog/2022-03-07-part-2-using-redis-sessions-instead-of-cookie-store)

_Photo credit: [`oscrse`](https://unsplash.com/@oscrse)_
