mdv.io

💌 Adding your environment name to ActionMailer subjects

July 10, 2020

Wouldn’t it be nice to know which emails came from your staging app versus your production app? If you’re using Rails and ActionMailer, it’s a breeze.

Just open up app/mailers/application_mailer.rb and add the following after_action block:

# app/mailers/application_mailer.rb

class ApplicationMailer < ActionMailer::Base
  # ...

  after_action do
    mail.subject.prepend(ENV['MAILER_SUBJECT_PREFIX']) if ENV["MAILER_SUBJECT_PREFIX"]
  end
end

This will take whatever you have set in your environment as MAILER_SUBJECT_PREFIX and prepend it to your subject line.

For example, I use MAILER_SUBJECT_PREFIX="[STAGING] ”, and my Daily stats email subject line changes from:

  • from: 📈 Daily stats for July 10, 2020
  • to: [STAGING] 📈 Daily stats for July 10, 2020

Keep in mind, you don’t want to set this environment variable in production!

Alternatively, you can do this without Environment variables

Sometimes you don’t want to use Environment Variables, which is fine. Just modify the code above to look like:

# app/mailers/application_mailer.rb

class ApplicationMailer < ActionMailer::Base
  # ...

  after_action do
    mail.subject.prepend("[STAGING] ") if Rails.env.staging?
  end
end

And there you have it. Happy mailing!


💨🌳 Adding TailwindCSS to RedwoodJS

April 9, 2020

I’ve been playing around with RedwoodJS for some side projects lately and have been really enjoying it. Redwood is a full-stack JS framework built by Tom Preston-Werner (Co-Founder of Github) & others. Essentially, Redwood is Rails for modern JS stacks: opinionated, batteries-included, and well thought out.

Another tool I’ve been using heavily is TailwindCSS, especially when developing sites by writing reusable components, as one does with React and Vue. I can’t really say enough good things about Tailwind – I absolutely love it. My productivity has skyrocketed since I started using it – it’s like supercharging your front-end.

So, since I’ve been really digging these two libraries, the next logical step is to marry the two.

Redwood, meet Tailwind. Tailwind, meet Redwood.

TailwindCSS + RedwoodJS

Let’s do this.

1. First lets get a clean Redwood project going:

yarn create redwood-app ./redwood-with-tailwind
cd redwood-with-tailwind

2. And let’s add a basic homepage

yarn redwood generate page home /

Let’s test it out.

yarn rw dev

Now we’ve got a basic Redwood app up and running at http://localhost:8910 Let’s get things going with Tailwind.

3. Add PostCSS and TailwindCSS

Redwood already ships with Webpack by default, so we just need to add PostCSS and Tailwind to get rolling.

yarn workspace web add postcss-loader tailwindcss autoprefixer --dev

(NOTE: We’ve also added Autoprefixer to give wider browser support. Highly recommended.)

Let’s extend webpack to use PostCSS. We’ll do this by placing a new config file in web/config (which doesn’t exist by default):

mkdir web/config
touch web/config/webpack.config.js

Update this file to look like so:

// web/config/webpack.config.js

const configDir = __dirname

module.exports = (config) => {
  config.module.rules[0].oneOf[5] = {
    test: /\.css$/,
    sideEffects: true,
    use: [
      'style-loader',
      { loader: 'css-loader', options: { importLoaders: 1 } },
      {
        loader: 'postcss-loader',
        options: {
          config: {
            path: configDir,
          },
        },
      },
    ],
  }

  return config
}

This will ensure post-css is used to compile CSS. Next we’ll create a postcss config file:

touch web/config/postcss.config.js

And add the following contents:

// web/config/postcss.config.js

const path = require('path')

module.exports = {
  plugins: [
    require('tailwindcss')(path.resolve(__dirname, 'tailwind.config.js')),
    require('autoprefixer')
  ],
}

This ensures Tailwind is used when PostCSS is compiling the CSS. Almost there. Next we’ll initialize TailwindCSS:

yarn workspace web tailwindcss init
mv web/tailwind.config.js web/config/tailwind.config.js

And finally, we need to mport the ase Tailwind styles. Place the following in our web/src/index.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;

That’s it.

Now, let’s make sure it works.

Let’s start the server:

yarn rw dev

🎉 Tada. No styles.

Let’s add something. Open up web/src/index.css and add:

body {
  @apply bg-indigo-500;
}

Save the file and check out your browser. You should be seeing purple.

Well done. 👏

Everything is working right now, but it can be slightly better.

Taking it a step further: PurgeCSS

Tailwind is amazing but there’s very little chance you’re going to use the entire library in your app. Luckily, there’s PurgeCSS to help remove unused css classes and make your payload tiny. Let’s add it.

yarn workspace web add @fullhuman/postcss-purgecss --dev

And all we have to do is update our web/config/postcss.config.js file:

// web/config/postcss.config.js

const path = require('path')

const purgecss = require('@fullhuman/postcss-purgecss')({
  content: [
    path.resolve(__dirname, '..', 'src', '**', '!(*.test).js'),
    path.resolve(__dirname, '..', 'src', '**', '*.html'),
  ],
  // This extractor is used for tailwind classes.
  // Read more here: https://tailwindcss.com/docs/controlling-file-size/
  defaultExtractor: (content) => content.match(/[\w-/:]+(?<!:)/g) || [],
})

module.exports = {
  plugins: [
    require('tailwindcss')(path.resolve(__dirname, 'tailwind.config.js')),
    require('autoprefixer'),
    ...(process.env.NODE_ENV === 'production' ? [purgecss] : []),
  ],
}

This will cause PurgeCSS to look at all of our non-test files in the web/src directory, and remove any CSS that’s not used in those files.

⚠️ Note: this config only runs PurgeCSS in production, which is a sane default here. Otherwise you’d have to restart your redwood process on each CSS change. It is a good idea to test the changes in development before shipping, however.

One final change needs to be made. Open up web/src/index.css and modify the Tailwind imports like so:

/* purgecss start ignore */
@tailwind  base;
@tailwind  components;
/* purgecss end ignore */

@tailwind  utilities;

And there you have it, all the power of TailwindCSS inside of RedwoodJS, without any extra bloat.

Happy coding.


🥞 This stack

April 8, 2020

UPDATE (June 11, 2020): I’ve switched this site to use Jekyll on Github Pages.

The current stack is:

  • Jekyll for static site generation. I had used GatsbyJS previously, but after spending time trying to get Server-Side Rendering working, I realized I had gone too far.
  • TailwindCSS for styling. I have too much love for Tailwind.
  • Netlify for hosting. My initial plan was to use Github Pages for hosting, and I may go back there, but Netlify has been nothing short of fantastic for my other projects, so I thought what the hell.

The former stack:

  • GatsbyJS for static site generation. I tend to prefer Vue over React, so I looked at Gridsome originally. but it seems to be nothing more than a Vue knockoff of Gatsby, so I went with the original.
  • TailwindCSS for styling. I have too much love for Tailwind.
  • Netlify for hosting. My initial plan was to use Github Pages for hosting, and I may go back there, but Netlify has been nothing short of fantastic for my other projects, so I thought what the hell.