Devise Customization Resources
There are a number of free resources that discuss customization of Devise, including Devise Wiki, RailsCasts #209 and RailsCasts #210. The RailsCasts episodes cover the following topics.

  1. Including and removing modules (e.g. confirmable and validatable)
  2. Configuring Devise messages in devise.en.yml
  3. Customizing Devise views by using templates to override them – generating these templates via the devise:views generator.
  4. Customizing authentication routing by adding options to the devise_for call in routes.rb
  5. Customizing fields used for authentication – e.g. using a username field instead of the default email field.
  6. Customizing validations when a user signs up for an account by changing configuration options in devise.rb.

Beyond Layouts
What if, instead of just changing the styles of existing forms or adding additional layouts, you want to change where the forms are rendered in your application (e.g. you want sign up and sign in forms located inside another view)? And what are the considerations that follow this new placement? A failed registration will still redirect to Devise's default sign up path (not the new form location you implemented) unless these redirects are updated via a controller. And how do you make sure error messages are displayed on your new view. When I wanted to render devise sign in and sign up forms as partials on the welcome page of my application, Wikit, this was the problem and follow up customization issues that needed to be addressed. The efficacy of the following solutions are limited to the scope in which Devise was used in that application. It has not been tested beyond that (e.g. with models that inherit from another Devise model).
On his blog, J. Fernández offers a solution for showing Devise forms on another page. Devise Wiki posts it as well, with some revisions. As Fernández suggests, I found the use of a partial as the best way to use the form on another view.
app/views/welcome/index.html.erb
<div class="col-md-4 col-sm-6">
    <a name="signin"></a>
    <div class="center-div">  
        <%= render "devise/sessions/form" %>
    </div>
</div>
 
app/views/devise/sessions/_form.html.erb
<div>
<h3 style="margin-top:0">Sign In</h3>
<%= form_for(:user, :url => session_path(:user), :html => { :class =>
'auth-form-for'}) do |f| %>
    <p><i class="fa fa-envelope-o" aria-hidden="true"></i><%= f.text_field :email, placeholder: "email", class: "auth-form" %></p>
    <p><i class="fa fa-lock" aria-hidden="true"></i><%= f.password_field :password, autocomplete: "off", placeholder: "password", class: "auth-form" %></p>
    <p><%= f.check_box :remember_me %>&nbsp;<%= f.label :remember_me %></p>
    <p><%= f.submit 'Sign in' %></p>
    <p><%= link_to "Forgot your password?", new_password_path(:user) %></p>
    <p><%= link_to "Didn't receive confirmation instructions?", new_user_confirmation_path(:user) %></p>
<% end %>
</div>

<div>
<h3>New User</h3>
<%= form_for(:user, :url => registration_path(:user), :html => { :class =>
'auth-form-for'}) do |f| %>
    <p><i class="fa fa-envelope-o" aria-hidden="true"></i><%= f.text_field :email, placeholder: "email", class: "auth-form" %></p>
    <p><i class="fa fa-lock" aria-hidden="true"></i><%= f.password_field :password, autocomplete: "off", placeholder: "password", class: "auth-form" %></p>
     <% if @minimum_password_length %>
     <em>(<%= @minimum_password_length %> characters minimum)</em>
     <% end %>
    <p><i class="fa fa-lock" aria-hidden="true"></i><%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "confirm password", class: "auth-form" %></p>
    <p style="margin-top:15px"><%= f.submit 'Sign up' %></p>
<% end %>
</div>
 
The second part of this solution, addressed by Fernández, involves resource mapping to ensure that the methods relied on by the forms are accessible. I placed them in ApplicationController.
Consistent User Flow
The solution above allowed Devise methods to be used from a partial. The remaining issues, however, were maintaining consistency in user flow in the event of failures, and handling error messages. With the above implementation, a failed authentication or registration still redirects to the default Devise paths/views. But if a user fails to authenticate or sign up from the welcome page, they should be redirected to the welcome page and see the error messages for the failure there.
In order to customize the redirect and error message display for failed registration, you can subclass Devise::RegistrationsController and override the create action. The default Devise views use a call to <%= devise_error_messages! %> to display resource.errors, but I wanted to display them to flash[:danger]. The value for flash[:danger] is set inside create, using the map method on resource.errors to display the items in list form.
app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

    def create
        build_resource(sign_up_params)
    
        if resource.save
            yield resource if block_given?
            if resource.active_for_authentication?
                set_flash_message :notice, :signed_up if is_flashing_format?
                sign_up(resource_name, resource)
                respond_with resource, location: after_sign_up_path_for(resource)
            else
                set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
                expire_data_after_sign_in!
                respond_with resource, location: after_inactive_sign_up_path_for(resource)
            end
        else
            clean_up_passwords resource
            flash[:danger] = resource.errors.full_messages.map { |error| "<li>#{error}" }.join("</li>")
            redirect_to root_path
        end
    end
...
 
Also, because html_safe is not preserved from the controller to the view, it is called in application.html.erb instead, <%= flash[:danger].html_safe %>. Redirects after a failed authentication needed to be customized as well. This can be done with a CustomFailure class. As flash[:danger] is used for error messages, that is set in def respond.
lib/custom_failure.rb
class CustomFailure < Devise::FailureApp

  def respond
    if http_auth?
      http_auth
    else
        flash[:danger] = i18n_message
        redirect_to welcome_index_path
    end
  end
end
 
Other Customizations: styles, messages, & paths
Other customizations included the following: styling the passwords/new and confirmations/new views to match (but not duplicate) the style of the sign in and sign up forms; removing messages for successful sign up and sign in, by editing them in devise.en.yml; and editing paths for certain links in shared/_links. Additional controllers were also implemented to customize redirects on password recovery and resending confirmation actions.
app/controllers/confirmations_controller.rb
def after_resending_confirmation_instructions_path_for(resource_name)
  is_navigational_format? ? root_path(resource_name) : '/'
end
 
app/controllers/passwords_controller.rb
class PasswordsController < Devise::PasswordsController
  protected
  def after_sending_reset_password_instructions_path_for(resource_name)
    return root_path 
  end
end
 
I hope this post was useful in understanding the how and why of the customized Devise implementations in this portfolio's apps. Even better if you learned something about using Devise forms on different pages in your app, and correspondingly handling paths and Devise messages.