mjml-rails

repository·master·Indexed 43 days ago

https://github.com/sighmon/mjml-rails

A Ruby gem that enables Rails developers to render HTML emails using MJML templates. It supports the standard Node.js-based MJML engine and a Rust-based implementation (MRML) for environments where Node.js is unavailable. The gem integrates with ActionMailer, supports Rails layouts, and provides a generator for MJML-enabled mailers.

Tokens
3.2K
Snippets
13
Records
17
Agent score
55%

What's inside mjml-rails

  1. Override Devise mailer with MJML

    master

    To use MJML templates with Devise, create a custom mailer inheriting from Devise::Mailer and configure Devise to use it. Ensure you call format.mjml in your mail block.

    # app/mailers/devise_mailer.rb
    class DeviseMailer < Devise::Mailer
      def reset_password_instructions(record, token, opts={})
        @token = token
        @resource = record
        mail(
          template_path: 'devise/mailer',
          from: "some@email.com",
          to: record.email,
          subject: "Custom subject"
        ) do |format|
          format.text
          format.mjml
        end
      end
    end

    config/initializers/devise.rb

    config.mailer = 'DeviseMailer'

  2. Install MJML-Rails via Rails generator

    master

    To set up MJML-Rails in your application, run the MJML install generator. This will create the necessary configuration file at config/initializers/mjml.rb to manage your MJML settings.

    rails generate mjml:install
  3. Use Rails Email Layouts with MJML

    master

    You can use standard Rails layouts with MJML. If you specify a layout (e.g., layout "default"), the mailer will look for default.html.mjml or default.html.erb.

    Warning: If default.html.erb exists, the email will be rendered as standard ERB and MJML tags will NOT be compiled.

    # mailers/my_mailer.rb
    class MyMailer < ActionMailer::Base
      layout "default"
    
      def foo_bar(user)
        mail(to: user.email, from: "app@example.com") do |format|
          format.html
        end
      end
    end
    <!-- views/layouts/default.html.mjml -->
    <mjml>
      <mj-body>
        <%= yield %>
      </mj-body>
    </mjml>
  4. Install mjml-rails using MRML (No Node.js required)

    master

    If you cannot run JavaScript in your production environment, you can use mrml, a Rust-based implementation of MJML that ships with precompiled binaries. This removes the need for an external Node.js dependency.

    Note: MRML does not support all MJML functionalities.

    # Gemfile
    gem 'mjml-rails'
    gem 'mrml'
    bundle install
    # config/initializers/mjml.rb
    Mjml.setup do |config|
      config.use_mrml = true
    end
  5. Render MJML templates in ActionMailer

    master

    To render MJML in a mailer, include format.mjml in your mail block. You can use ERB or other template languages inside your .mjml files.

    Example template structure:

    • app/views/user_mailer/user_signup_confirmation.mjml
    • app/views/user_mailer/_info.html.erb (partial)
    # ./app/mailers/user_mailer.rb
    class UserMailer < ActionMailer::Base
      def user_signup_confirmation
        mail(to: "user@example.com", from: "app@example.com") do |format|
          format.text
          format.mjml
        end
      end
    end
    <!-- ./app/views/user_mailer/user_signup_confirmation.mjml -->
    <mjml>
      <mj-body>
        <mj-section>
          <mj-column>
            <mj-text>Hello World</mj-text>
            <%= render partial: "info", formats: [:html] %>
          </mj-column>
        </mj-section>
      </mj-body>
    </mjml>
  6. Install mjml-rails using NPM

    master

    To use the standard MJML implementation, add the gem to your Gemfile and install the mjml package using your preferred Node package manager.

    Note: MJML v5 requires Node.js 20+.

    For Rails 7.x with importmaps, installing MJML globally is recommended.

    # Gemfile
    gem 'mjml-rails'
    bundle install
    rails generate mjml:install
    
    # Install MJML via npm
    npm install mjml
    
    # OR install globally (recommended for Rails 7 + importmaps)
    npm install -g mjml
    
    # OR via yarn
    yarn add mjml
    
    # OR via bun
    bun add mjml
  7. Deploy mjml-rails to Heroku

    master

    Deploying to Heroku requires multiple buildpacks: heroku/ruby and heroku/nodejs. The Node.js buildpack must be at index 1 so it runs before the Ruby buildpack. You must also include a package.json in your root directory containing mjml in the dependencies.

    # Set buildpacks
    $ heroku buildpacks:set heroku/ruby
    $ heroku buildpacks:add --index 1 heroku/nodejs
    
    # Verify
    $ heroku buildpacks
    // package.json
    {
      "dependencies": {
        "mjml": "^5.0.0"
      }
    }
  8. How MJML binary discovery works

    master

    The Mjml module attempts to find a valid MJML binary in the following order:

    1. Custom Binary: Any path explicitly set via Mjml.mjml_binary=.
    2. MRML: If Mjml.use_mrml is enabled and the MRML constant is present.
    3. Bun: If bun is installed, it attempts to run bun run mjml (prioritizing local bins).
    4. NPM/Yarn Package: Looks for the mjml binary within node_modules via npm root or yarn bin.
    5. Global Installation: Searches for a globally installed mjml command using the system's which or where command.

    Every discovered binary is validated against Mjml.mjml_binary_version_supported to ensure compatibility.

  9. Configure mjml-rails settings

    master

    Use the Mjml.setup block in config/initializers/mjml.rb to customize the rendering engine.

    Important: When use_mrml is set to true, the following options are ignored: mjml_binary_version_supported, mjml_binary, minify, beautify, and validation_level.

    # config/initializers/mjml.rb
    Mjml.setup do |config|
      # Use :haml as a template language
      config.template_language = :haml
    
      # Ignore errors silently
      config.raise_render_exception = false
    
      # Optimize the size of your emails
      config.beautify = false
      config.minify = true
    
      # Render MJML templates with errors
      config.validation_level = "soft"
    
      # Use MRML instead of MJML, false by default
      config.use_mrml = false
    
      # Use custom MJML binary with custom version
      config.mjml_binary = "/path/to/custom/mjml"
      config.mjml_binary_version_supported = "3.3.5"
    
      # Use default system fonts instead of google fonts
      config.fonts = {}
    
      # Uncomment this to enable template caching
      # config.cache_mjml = true
    end
  10. Generate an MJML-enabled mailer

    master

    Use the mjml:mailer generator to create a new mailer that supports MJML templates. This generator extends the standard Rails mailer generator but configures the file extensions and handlers to support MJML processing.

    When using this generator, the resulting files will follow these naming conventions:

    • Layout files: Must have the .mjml extension (e.g., application.mjml).
    • View/Template files: Use the configured MJML template language extension (e.g., .mjml or .erb depending on Mjml.template_language) but are handled by the MJML engine.
    rails generate mjml:mailer UserMailer user
  11. Configure MJML as the default mailer template engine

    master
    When the mjml-rails gem is loaded, it automatically configures Rails to use MJML as the template engine for mailers. This allows you to create .mjml template files that are automatically compiled into HTML. The Railtie registers the :mjml template handler and aliases text/html to :mjml to ensure seamless integration with ActionView.
  12. Reference: mjml-rails configuration options

    master

    The following configuration keys are available within the Mjml.setup block:

    template_language: :erb (default) - Supports :haml, :slim, etc.
    raise_render_exception: true (default) - If false, exceptions result in empty HTML.
    minify: false (default) - HTML minification.
    beautify: true (default) - Formats HTML syntax.
    validation_level: "strict" (default) - "soft" allows rendering invalid templates.
    mjml_binary: nil - Path to custom MJML binary.
    mjml_binary_version_supported: "5." - Version prefix check.
    use_mrml: false (default) - Enables Rust-based MRML implementation.
    cache_mjml: false (default) - Caches compiled templates in tmp/mjml_cache.
    fonts: {} - Hash to override default MJML fonts (e.g., { Raleway: 'url' }).