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 markdown.db
under 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)
Create your legal controller
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 called imprint.md
views/markdown/imprint.md
# Imprint
---
**Jon Doe**
Demo Street 10
12345 Demo City
Germany
Update your legal controller to read your Markdown file
Update your legal_controller.rb
to read you 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 if to keep the prose
class from Tailwind
As your text will have no styling otherwise.
Extra Config for Inertia users
If you are not using Inertia, you can skip this!
If you are using Inertia
You probably noticed that your imprint page does not look quite right. We need to make two more modifications.
- 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 inertia><= content_for(:title) || "React Starter Kit" %></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">
<= capybara_lockstep if defined?(Capybara::Lockstep) %>
<= 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">
<script>
<%# Enable dark mode based on localStorage or system preference. Inline to avoid FOUC. %>
document.documentElement.classList.toggle(
"dark",
localStorage.appearance === "dark" ||
(!("appearance" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches),
);
</script>
<%= vite_stylesheet_tag "application" %>
<%= vite_client_tag %>
</head>
<body>
<= yield %>
</body>
</html>
And then tell your legal_controller.rb
to use the new layout by adding layout "none_inertia"
to. 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}";