How to render markdown in your Rails app

September 22, 2025

If you are like me and you’re regularly spinning up new websites for your side projects, you probably created a handful of legal pages. To save time, I started to build my legal pages with markdown and just render a Notion-style white page with the required text. This allows me to copy and paste my legal pages between my projects. In this blog post, I want to show you how you can set up your rails app to render markdown views. Even if you are using Inertia!

Prerequisites/ Assumptions

  • Rails 8 or newer
  • Tailwind CSS
  • Tailwindcss-Typography to style the text (https://github.com/tailwindlabs/tailwindcss-typography)

Install the Redcarpet gem

Install the Redcarpet gem to render markdown by adding the following to your gemfile

gem "redcarpet"

and run

bundle install

Create an initializer

Create a new file called

config/initializers/markdown.rb

and add the following content to it.

# frozen_string_literal: true
MARKDOWN = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)

Run

rails g controller Legal imprint

Create a folder with your markdown files.

Under views create a new folder called markdown for all your markdown files. Then create your first markdown file:

views/markdown/imprint.md
# Imprint

---

**Jon Doe**
Demo Street 10
12345 Demo City
Germany

Update your

legal_controller.rb

to read your

imprint.md

and return its content as an instance variable

class LegalController < ApplicationController
  def imprint
    md_path = Rails.root.join("app", "views", "markdown", "imprint.md")
    @content = MARKDOWN.render(File.read(md_path)).html_safe
  end
end

Update your imprint view to render your markdown.

Replace the content of

imprint.html.erb

with the following code

<div class="p-4">
  <= link_to root_path, class: "inline-flex items-center justify-center w-12 h-12 rounded-full border border-gray-300 bg-white shadow hover:bg-gray-100" do %>
    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
      <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 19.5 3 12m0 0 7.5-7.5M3 12h18"/>
    </svg>
  <% end %>
</div>

<div class="p-4 prose mx-auto">
  <= @content %>
</div>

The important part here is to keep the prose class from Tailwind as your text will have no styling otherwise.

And that's it! You can now start your rails server and navigate to

http://localhost:3000/legal/imprint

to see your markdown rendered as HTML.

Extra Config for Inertia users

If you are using Inertia you probably noticed that your imprint page does not look quite right. We need to make two more modifications.

  1. Create a non-inertia layout.

The following is just a copy & paste of the default Inertia layout minus the react vite tags:

views/layouts/none_inertia.html.erb
<!DOCTYPE html>
<html>
<head>
  <title><= content_for(:title) || "Pwa Rails" %></title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="mobile-web-app-capable" content="yes">
  <= csrf_meta_tags %>
  <= csp_meta_tag %>

  <= yield :head %>

  <%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
  <%= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>

  <link rel="icon" href="/icon.png" type="image/png">
  <link rel="icon" href="/icon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="/icon.png">

  <%# Includes all stylesheet files in app/assets/stylesheets %>
  <= vite_stylesheet_tag "application" %>
</head>

<body>
<main class="container mx-auto mt-28 px-5 flex">
  <= yield %>
</main>
</body>
</html>

And then tell your

legal_controller.rb

to use the new layout by adding

layout "none_inertia"

So the final controller will look like:

# frozen_string_literal: true
class LegalController < ApplicationController
  layout "none_inertia"
  skip_before_action :authenticate
  def imprint
    md_path = Rails.root.join("app", "views", "markdown", "imprint.md")
    @content = MARKDOWN.render(File.read(md_path)).html_safe
  end
end

Then update your

application.css

and tell Tailwind where it can find your ERB templates:

@source "../../views/**/*.{erb,html,html.erb}";