DEV Community

Cover image for Creating a deployable Rails 6 app + TailwindCSS, Stimulus.js, and a custom font.
Bob Walsh
Bob Walsh

Posted on • Updated on • Originally published at 47hats.com

Creating a deployable Rails 6 app + TailwindCSS, Stimulus.js, and a custom font.

This post covers how to set up a new Rails 6 app to use Tailwind CSS, and then set up a custom body font, and get the whole thing actually working when deployed to Heroku.

If you haven't upgraded your Rails skills to 6, be prepared to be shocked: Rails 6 fully works with modern JS frameworks the way they expect to be worked with. While there's still the asset pipeline, it's deprecated for the javascript hotness.

The first and most important step is don't pick the wrong tutorials to follow, or your path will be one of frustration and pain. I initially wanted to run Vue.js from within Rails 6, and I figured that was going to be the most difficult integration. I started by Googling "Rails 6 Vue js" and found this How to Integrate Vue.js with Rails 6
and through trial and much error, integrated Tailwind with it.

So there I was with Rails6, Vue, and Tailwind sitting in a tree. Unfortunately, I kept getting a compile error on Heroku that was not happening on localhost. Damn!

So after several days for fruitlessly trying to debug this issue and rethinking things a bit, I realized I was better off sticking with what I know and coloring within the lines that the people who wrote Rails have laid down: Rails for the main thing, and Stimulus.js to handle the "jQuery-like" simple but essential stuff like triggering dropdowns.

Enough talk, show me the code!

Ok, here we go.

  1. with the current rails/ruby in your present working directory, rails new <appname.
  2. The install Stimulus with rails webpacker:install:stimulus (see this GoRails video: How to use Javascript via webpacker in Rails 6 (and Flatpickr) for an excellent tutorial.)
  3. app/javascript/packs/application.js is very much like the old asset pipeline; add this code:

    import "controllers"
    import flatpickr from "flatpickr"
    
    require("flatpickr/dist/flatpickr.css")
    

    The first line sets up stimulus controllers, then the next lines set up flatpickr. then this code:

    document.addEventListener("turbolinks:load", () => {
      flatpickr("[data-behavior='flatpickr']", {
        altInput: true,
        altFormat: "F j, Y",
        dateFormat: "Y-m-d",
      })
    })
    

    configures what HTML tags should be inited with flatpickr and what the input and display date formats in flatpickr should be.
    And don't forget to add flatpickr to your rails project: yarn add flatpickr.

    [A small digression: pick either yarn or npm and stick to that. Otherwise, you end up with a yarn.lock and a package-lock.json file in contention for control of your package.json. Bad idea. For this project I went with yarn, and recommend this cheatsheet for translating npm into yarn: NPM vs Yarn Cheat Sheet.]

    Next, it's time to see flatpickr at work in a view. Scaffold a view and then replace a form.date_select with a form.text_field :publish)date, date, { behavior: "flatpickr"} you should now in have a much nicer view working:

    Alt Text

    By the way, it seems Rails 6 is using a whole new form syntax: cleaner than the old one, hopefully easier to deal with when it comes time to add Tailwind classes.

    Now would be a good time to stick your project up on Heroku. Unless you know you are going to deploy via AWS, Heroku makes it easy to deploy and manage. Read this post, Getting Started on Heroku with Rails 6.x. if you need to brush up.

    Implementing TailwindCSS

  • You'll do a yarn add tailwindcss@latest. Why latest? Because you want the latest stable build of TailwindCSS. Now you have TailwindCSS in your project, but not yet integrated. You should pull up the Tailwind Install instructions, keeping in mind you need to get Tailwind working in your Rails 6 project. Check out GoRails How to install TailwindCSS 1.0 with Rails 6 if you want the full context, but here are the steps:

  • After doing yarn add tailwindcss, you need to create a new stylesheets directory in your javascript folder, and in that directory create an application.scss file to hold Tailwind's configuration:

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
Enter fullscreen mode Exit fullscreen mode
  • In postcss.config.js, you need to require('tailwindcss') and on the next line, require('authoprefixer').
  • One more step: telling webpack about this new application.scss. Do that in application.js with a require("stylesheets/application.scss") declaration.
  • Now you need to employ some tailwindCSS. For an easy way to do this, copy a navbar here and add it to /layout/application.html.erb.
  • You should have everything working in your Rails Project: do a quick test by having webpack compile by running from your CLI bin/webpack, and then try running it in localhost.

Installing a custom font into a Rails 6 app

As the final step I want to capture in this tutorial, here are the steps needed to use a custom font. Gone is declaring a CDN in the <head> tag, or shoehorning a set of fonts into your asset pipeline. There's a much cleaner way, the Javascript way:

  • Find the font as an npm module at npmjs.com. most font npm modules are going to start with interface- so pick one you like Roboto, or Nunito, or the awesome Inter font. Then add it to your project. For example yarn add 'typeface-inter'.
  • Now you need to tell Tailwind about this font in three places. First, edit your application.js file to include the npm module:
require("channels")
require('typeface-inter')

require("stylesheets/application.scss")
Enter fullscreen mode Exit fullscreen mode
  • Next, generate a tailwind.config.js file in the root of your project (npx unlike npm does not generate a package-lock.json file, so use that.)
  • Modify tailwind.config.js:
module.exports = {
  theme: {
    fontFamily: {
      body: ['inter']
    },
    extend: {},
  },
  variants: {},
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode
@import "tailwindcss/base";
html {
  @apply font-body;
}
@import "tailwindcss/components";
@import "tailwindcss/utilities";
Enter fullscreen mode Exit fullscreen mode

(Thanks to Scott Watermasysk and "Using Google Fonts Tailwind CSS" who graciously clarified for me where some of these bits need to go. Thanks Scott! (BTW, check out his How I VSCode project.)

Takeaways

Once again Rails has reinvented itself, this time as an excellent server application and as a container for all the javascript npm modules and frameworks large and small you might want to use.

That means all you Rails developers who know jQuery but are flummoxed by npm modules and all that javascript running loose need to bite the bullet, learn Rails 6, and get on board with it.

Once you make the mental switch to how webpacker works to integrate js into your rails app, it all starts making sense, and you can pretty much forget all those painful little workarounds in the asset pipeline.

And as Lee Smith just pointed out, while TailwindCSS starts out being a large package, larger than Bootstrap, you can easily add purgeCSS to your project so that when you push to production all those unused TailwindCSS classes get axed. The result? An ultrasmall and ultrasleek css file.

A final takeaway: The shelf life of developer information is now even shorter. Any tutorial, video, or post older than 6 months is suspect; older than a year, not trustworthy. That's a huge unmet need looking for a cool SaaS to solve it, in case you want to build the next Big Thing.

Latest comments (11)

Collapse
 
tonydehnke profile image
Tony Dehnke

Thanks for this, it was good, a bit hard to follow in some places as it's not clear where to put the code always. Would be great to have a linked sample repo to be able to view so we can see the full file examples if we need to. Thanks again!

Collapse
 
hansonryne profile image
hansonryne

Thanks for the article!

Couple typos in the flatpickr section:

form.text_field :publish)date, date, { behavior: "flatpickr"}

Should be

form.text_field :publish_date, data: { behavior: "flatpickr"}

Collapse
 
leesmith profile image
Lee Smith 🍻

Awesome stuff. I've always loved Rails and I'm really into TailwindCSS these days. Stimulus is still new to me...gotta write more JS with it in the future.

If I could make a suggestion though. Please cover PurgeCSS in your TailwindCSS installation material. Without PurgeCSS, deploying a Tailwind app to production will result in a large payload. They really work hand in hand.

Great post!

Collapse
 
bobwalsh47hats profile image
Bob Walsh

Good catch! Done.

Collapse
 
faraazahmad profile image
Syed Faraaz Ahmad

I started by Googling "Rails 6 Vue js"

Been there, done that 😅

Collapse
 
ben profile image
Ben Halpern

This seems like one fabulous stack

Collapse
 
leob profile image
leob • Edited

This:

"The shelf life of developer information is now even shorter. Any tutorial, video, or post older than 6 months is suspect"

is spot on, and is what I've been using as a guideline for a long time :-)

I don't get the remark about the unmet need for a SaaS though ... you mean a "system" or "app" to help developers obtaining up to date developer info?

Collapse
 
bobwalsh47hats profile image
Bob Walsh

I wasted several workdays trying to get an obsolete tutorial implemented. If there was a service that would use a Chrome extension to track obsolete posts and tutorials and warn me "hey, that post is the old way of doing such and such, see this post for the new shiny thing" I'd pay for it.

Collapse
 
leob profile image
leob

Right, but who is going to curate that information? That would be a huge and pretty boring task, assuming it would be manual. As you say, I simply don't put a lot of trust in info that's older than let's say half a year to a year.

Thread Thread
 
bobwalsh47hats profile image
Bob Walsh

Like a lot of things on the web, this idea requires user content. So let's say there's a Chrome extension that does two things: downvotes posts as now obsolete and upvotes posts that are "current". Kind of like all those coupon services we use to save a few bucks on site renewals.

So a developer goes to a post about adding an API to a Rails 6 app. The extension either does nothing (no info available), turns green (other developers have said this is a good current post) or red (other developers say this post is now outdated). This would be a huge timesaver!

It would be a no-brainer buy for individual developers and teams of developers, hence a viable SaaS.

Thread Thread
 
leob profile image
leob

You're right, I was thinking of that but then forgot to mention it. You need to "crowd source" the info, people would 'vote' content up or down. Might be a viable idea.