Skip to content

Rails-Designer/perron

Repository files navigation

Perron

A Rails-based static site generator.

Sponsored By Rails Designer

Rails Designer

Getting Started

Installation

Start by adding Perron:

bundle add perron

Then generate the initializer:

rails generate perron:install

This creates an initializer:

Perron.configure do |config|
  config.site_name = "AppRefresher"
end

Mode

Perron can operate in two modes, configured via config.mode. This allows you to build either a full static site or integrate pages into a dynamic Rails application.

Mode :standalone (default) :integrated
Use Case Full static site for hosts like Netlify/Vercel Add static pages to a live Rails app
Output output/ directory public/ directory
Asset Handling Via Perron Via Asset Pipeline

Creating Content

Perron is, just like Rails, designed with convention over configuration in mind. Content is stored in app/content/*/*.{erb,md}. Content is backed by a class, located in app/models/content/ that inherits from Perron::Resource.

The controllers are located in app/controllers/content/. To make them available, create a route: resources :posts, module: :content, only: %w[index show].

Collections

bin/rails generate content Post

This will create the following files:

  • app/models/content/post.rb
  • app/controllers/content/posts_controller.rb
  • app/views/content/posts/index.html.erb
  • app/views/content/posts/show.html.erb
  • Adds route: resources :posts, module: :content, only: %w[index show]

Setting a Root Page

To set a root page, include Perron::Root in your Content::PagesController and add a app/content/pages/root.[md,erb] file (make sure to set slug: "/" in its frontmatter).

This is automatically added when you create a Page collection.

Markdown Support

Perron supports markdown with the markdownify helper.

There are no markdown gems bundled by default, so you'll need to add one of these:

  • CommonMarker
  • Kramdown
  • Redcarpet
bundle add {commonmarker,kramdown,redcarpet}

HTML Transformations

Perron can post-process the HTML generated from your Markdown content.

Usage

Apply transformations by passing an array of processor names or classes to the markdownify helper via the process option.

<%= markdownify @resource.content, process: %w[target_blank lazy_load_images] %>

Available Processors

The following processors are built-in and can be activated by passing their string name:

  • target_blank: Adds target="_blank" to all external links;
  • lazy_load_images: Adds loading="lazy" to all <img> tags.

Creating Your Own

You can create your own processor by defining a class that inherits from Perron::HtmlProcessor::Base and implements a process method. Then, pass the class constant directly in the process array.

# app/processors/add_nofollow_processor.rb
class AddNofollowProcessor < Perron::HtmlProcessor::Base
  def process
    @html.css("a[target=_blank]").each { it["rel"] = "nofollow" }
  end
end
<%= markdownify @resource.content, process: ["target_blank", AddNofollowProcessor] %>

Data Files

Perron can consume structured data from YML, JSON, or CSV files, making them available within your templates. This is useful for populating features, team members, or any other repeated data structure.

Usage

To use a data file, instantiate Perron::Site.data with the basename of the file and iterate over the result.

<% Perron::Site.data.features.each do |feature| %>
  <h4><%= feature.name %></h4>
  <p><%= feature.description %></p>
<% end %>

File Location and Formats

By default, Perron looks up app/content/data/ for files with a .yml, .json, or .csv extension. For a features call, it would find features.yml, features.json, or features.csv. You can also provide a path to any data file, via Perron::Data.new("path/to/data.json").

Accessing Data

The wrapper object provides flexible, read-only access to each record's attributes. Both dot notation and hash-like key access are supported.

feature.name
feature[:name]

Feeds

The feeds helper automatically generates HTML <link> tags for your site's RSS and JSON feeds.

Usage

In your layout (e.g., app/views/layouts/application.html.erb), add the helper to the <head> section:

<head><%= feeds %></head>

To render feeds for specific collections, such as posts:

<%= feeds only: %w[posts] %>

Similarly, you can exclude collections:

<%= feeds except: %w[pages] %>

Configuration

Feeds are configured within the Resource class corresponding to a collection:

# app/models/content/post.rb
class Content::Post < Perron::Resource
  configure do |config|
    config.feeds.rss.enabled = true
    # config.feeds.rss.path = "path-to-feed.xml"
    # config.feeds.rss.max_items = 25
    config.feeds.json.enabled = true
    # config.feeds.json.max_items = 15
    # config.feeds.json.path = "path-to-feed.json"
  end
end

Metatags

The meta_tags helper automatically generates SEO and social sharing meta tags for your pages.

Usage

In your layout (e.g., app/views/layouts/application.html.erb), add the helper to the <head> section:

<head><%= meta_tags %></head>

You can render specific subsets of tags:

<%= meta_tags only: %w[title description] %>

Or exclude certain tags:

<%= meta_tags except: %w[twitter_card twitter_image] %>

Priority

Values are determined with the following precedence, from highest to lowest:

1. Controller Action

Define a @metadata instance variable in your controller:

class Content::PostsController < ApplicationController
  def index
    @metadata = {
      title: "All Blog Posts",
      description: "A collection of our articles."
    }
    @resources = Content::Post.all
  end
end

2. Page Frontmatter

Add values to the YAML frontmatter in content files:

---
title: My Awesome Post
description: A deep dive into how meta tags work.
image: /assets/images/my-awesome-post.png
author: Kendall
---

Your content here…

3. Collection configuration

Set site-wide defaults in the initializer:

class Content::Post < Perron::Resource
  # …

  config.metadata.description = "AI-powered tool to keep your knowledge base articles images/screenshots and content up-to-date"
  config.metadata.author = "Rails Designer"
end

4. Default Values

Set site-wide defaults in the initializer:

Perron.configure do |config|
  # …

  config.metadata.description = "AI-powered tool to keep your knowledge base articles images/screenshots and content up-to-date"
  config.metadata.author = "Rails Designer"
end

Related Resources

The related_resources method allows to find and display a list of similar resources from the same collection. Similarity is calculated using the TF-IDF algorithm on the content of each resource.

Basic Usage

To get a list of the 5 most similar resources, call the method on any resource instance.

# app/views/content/posts/show.html.erb
@resource.related_resources

# Just the 3 most similar resources
@resource.related_resources(limit: 3)

XML Sitemap

A sitemap is an XML file that lists all the pages of a website to help search engines discover and index content more efficiently, typically containing URLs, last modification dates, change frequency, and priority values.

Enable it with the following line in the Perron configuration:

Perron.configure do |config|
  # …
  config.sitemap.enabled = true
  # config.sitemap.priority = 0.8
  # config.sitemap.change_frequency = :monthly
  # …
end

Values can be overridden per collection…

# app/models/content/post.rb
class Content::Post < Perron::Resource
  configure do |config|
    config.sitemap.enabled = false
    config.sitemap.priority = 0.5
    config.sitemap.change_frequency = :weekly
  end
end

…or on a resource basis:

# app/content/posts/my-first-post.md
---
sitemap_priority: 0.25
sitemap_change_frequency: :daily
---

Building Your Static Site

When in standalone mode and you're ready to generate your static site, run:

RAILS_ENV=production rails perron:build

This will create your static site in the configured output directory (output by default).

Sites using Perron

Sites that use Perron.

Standalone (as a SSG)

Integrated (part of a Rails app)

Contributing

This project uses Standard for formatting Ruby code. Please run be standardrb before submitting pull requests. Run tests with rails test.

License

Perron is released under the MIT License.

Sponsor this project

 

Languages