How To Integrate a Shuffle.dev TailwindCSS Theme In Rails 7


Share this post:

Soooooo . . . I can't stop building stuff.  Love it.  My latest little side project is a food/calorie/nutrition tracking app that does (nearly) everything via text message.  

I've gotten into TailwindCSS because I never took the time to properly learn CSS.  Love it!  Three cheers for laziness.

Rails 7 makes installing Tailwind a breeze, and Shuffle.dev makes creating Tailwind themes a snap.  I'll eventually get around to implementing ButterCMS with this Rails/Tailwind setup, but for now let's focus on the task at hand.  How does one integrate a Shuffle.dev theme into a new Rails 7 project that's already set up with Tailwind?  Let's dive in.

Getting Started - Create Your Rails App and Downloading Your Theme

To start, create a new Rails 7 app with Tailwind.

rails new textmymeals --css tailwind --database=postgresql

Super, now that we've got that done, grab your theme from Shuffle.dev. In this example, I'll be using their Flex theme, which is a combo landing and admin theme. 

To get the files, go to your project and download the views as HTML files:

Export as HTML

Awesome, now we've got our brand new Rails app, and our shiny new theme files. Now let's mix them together and make some magic.

Applying Your Shuffle Theme To Your Rails App

When you download your Shuffle theme, you'll see a folders structure like this:

Theme files from Shuffle.dev download

And your Rails 7 app will look something like this:

Basic Rails 7 File Structure

And if you run your Rails app (I added a pages controller and simple index view), you'll see something like this:

Hello world, how are you?

Ok, so now to move the files over that we need.  In this example, I just created a sample homepage, so let's get that over.  For step 1, let's focus on the "src" folder in our Tailwind theme. We'll start by copying over the contents of the index.html file and putting into our application layout.  Grab everything between the <body> tags, and grab the body class as well.  I don't care about charting libraries for this project, so you don't need to include any <script> tags that reference charts.

Step 1: copy index code over

The resulting code looks like this.  Note I left the <%= yield %> tag in up top - more on that in a bit.

Code - step 1.

Refreshing our browser shows us this. All the images are broken and the fonts don't match, but we've got signs of life.

Broking images everywhere!

Getting Images to Work

Let's get the images working first. You'll notice that the theme download contains EVERY image needed for the entire theme. Including all of them is overkill, so I like to check the logs to see what's missing.  You'll see lines like this:

17:03:37 web.1  | ActionController::RoutingError (No route matches [GET] "/flex-ui-assets/elements/pattern-white.svg"):
17:03:37 web.1  |   
17:03:37 web.1  |   
17:03:37 web.1  | ActionController::RoutingError (No route matches [GET] "/flex-ui-assets/elements/cta/men-computer-placeholder.png"):
17:03:37 web.1  |   
17:03:37 web.1  |   
17:03:37 web.1  | ActionController::RoutingError (No route matches [GET] "/flex-ui-assets/elements/dots3-blue.svg"):
1

Go through each of those errors and copy over the image.  You can create the necessary folders ("/flex-ui-assets/elements/" in this case) or go through the html to update the paths.  I'll just create the necessary folders for simplicity.  You will need to update the html code with Rails image tags however.  So this:

<img class="h-8" src="flex-ui-assets/logos/flex-ui-green-light.svg" alt="">

Becomes this:

 <%= image_tag "flex-ui-assets/logos/flex-ui-green-light.svg", :class => "h-8" %>

Tip: you'll likely run into some inline background images, you can use the image_path helper to fix those.

<section class="relative py-24 md:pb-32 bg-white overflow-hidden" style="background-image: url(<%= image_path('flex-ui-assets/elements/pattern-white.svg') %>); background-position: center;" >

Keep going through all the errors until you've squashed them all.  That gives us this:

Looking better!

Next Up, The Tailwind Theme Settings

Ok, now that we've nailed down the images, let's hit the Tailwind them settings.  You can find these in your Shuffle theme files here:

Shuffle theme settings

You'll find the corresponding file in Rails here: 

Tailwind theme file in Rails

So what do you copy over? Just the theme and variants sections:

Copy this over to your Rails tailwind.config.js file

Refreshing the site then gives us this...

Much better!

Don't Forget the Javascript!

Javascript and I really don't get along. I just never took the time to learn it. Our theme has a bit of javascript for the burger menu icon on small screens to display and hide the side menu.  You can see it here in the theme files:

Main.js - has the code to show/hide the menu

The cheaterpants way to include this would just be to drop in in some <script> tags in the application layout html itself.  However, that's not very Rails-ey, so let's see if we can figure it out using Stimulus.js.  Turns out Rails 7 boilerplate includes a "hello world" stimulus js file here: 

That's helpful.

Here's a great little article that helped me on setting up a new Rails 7 project with Tailwind and Stimulus.  Updating your code in your index view to this:

<div>
  <h1 class="font-bold text-4xl text-blue-500">Public#index</h1>
  <p>This is the index.html.erb file.  You're great.</p>
  <p data-controller="hello"></p>
</div>

Will produce this when you refresh the page:

Well hello there big world.

Notice the "Hello World!"?  That came from the hello_controller.js stimulus file.  Using the data-controller="hello" attribute in our paragraph tag tied that element to the javascript, which then updated the contents of that paragraph.

So how can we use this in our template to show and hide the navigation?  I am going to jump to the solution here, as stimulus makes this quite easy (once you understand it).  Instead of all those lines of javascript, we just need a stimulus controller that looks like this. I named mine navigation_controller.js.

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["sidemenu"]
  
  toggle(event)
  {
    event.preventDefault()
    this.sidemenuTarget.classList.toggle("hidden")
  }
}

I put the file here:

Navigation Stimulus Controller

And then update a few things in your HTML in the application layout to tie things together:

          <button data-action="navigation#toggle" class="navbar-burger self-center xl:hidden">

 and...

        <div data-navigation-target="sidemenu" class="navbar-menu hidden fixed top-0 left-0 z-50 w-full h-full bg-coolGray-900 bg-opacity-50">
         <div class="fixed top-0 right-0 bottom-0 left-0" data-action="click->navigation#toggle"> </div>

And that does it!

The Rest Of The Nitty Gritty Details

You'll notice we still have that ugly stuff on top, and haven't extracted tings into the correct partials, etc. yet. The next steps are to go through and slice up the theme html into the appropriate page parts - shared navigation files, application layout html, view specific html, etc.  I'll spare you the boredom of doing that, but get to it you lazypants.

Conclusion

Combining Rails 7, TailwindCSS and Shuffle.dev themes lets even the most design/css challenged produce a wonderful looking site with easy.  Happy coding!