CMS for Rails: Stop Rebuilding WordPress One Gem at a Time

Skip reimplementing publishing, media, and SEO by hand

August 2, 2026 · 5 min read
CMS for Rails: Stop Rebuilding WordPress One Gem at a Time

Rails developers have a reflex when someone says "we need a CMS": reach for a gem. And often that's right — a small blog can be a scaffold and a Post model in an afternoon. But the moment marketing wants scheduled publishing, a media library, SEO fields, categories, and draft previews, you're rebuilding a CMS by hand, one gem and one migration at a time. That's weeks of work maintaining something that isn't your product.

The alternative is a headless CMS that lives outside Rails and feeds it content over an API. This post covers when that beats rolling your own, how to wire it in, and the honest tradeoffs.

Build it in Rails, or connect a headless CMS?

Roll your own with ActiveAdmin, Administrate, or a hand-built controller: full control, everything in Ruby, but you own every feature. Media handling, publishing workflow, SEO metadata, image variants — all yours to build and maintain.

Headless CMS: content lives in a dedicated service with a ready-made admin and API. Rails fetches it. You skip building the editor entirely; non-developers get a real tool; your Rails app stays focused on the parts that are actually your product.

The tipping point is who edits and how much content workflow you need. A developer-only blog? A gem is fine. A team with writers, a publishing calendar, and clients? A headless CMS saves you from reimplementing WordPress badly.

Fetching CMS content in Rails

The integration is a plain HTTP call from a controller. Use Net::HTTP, Faraday, or HTTParty:

# app/controllers/blog_controller.rb
require "net/http"
require "json"

class BlogController < ApplicationController
  CMS = "https://cms.yoursite.com/api/v1"

  def index
    res = Net::HTTP.get(URI("#{CMS}/posts?per_page=20"))
    @posts = JSON.parse(res)["data"]
  end

  def show
    uri = URI("#{CMS}/posts/#{params[:slug]}")
    response = Net::HTTP.get_response(uri)
    raise ActionController::RoutingError, "Not Found" if response.code == "404"
    @post = JSON.parse(response.body)["data"]
  end
end

Wrap it in Rails' caching (Rails.cache.fetch) so you're not calling the API on every request. The CMS returns a consistent { success, message, data } shape, and drafts return 404, so you never render unpublished content.

Why self-hosted headless fits the Rails ethos

Rails developers value convention, ownership, and running their own stack. A SaaS CMS with metered API pricing and vendor-locked data goes against that grain. A self-hosted CMS keeps content under your control.

UnfoldCMS is one option. It's a self-hosted CMS built on Laravel with a REST API at /api/v1/* and a React + shadcn/ui admin. It's Ruby-agnostic by design — headless means the CMS is a service that speaks HTTP, so your Rails code only ever sees JSON. Run it on your own server, own the database, no per-request bill.

For Rails teams:

  • REST + JSON — maps cleanly to Faraday and view templates. No GraphQL client needed.
  • No gem to add — the integration is standard HTTP, nothing in your Gemfile to maintain.
  • Self-hosted, pay once — no usage metering on a content API you call constantly.

Cache busting with webhooks

Cache CMS responses and you need to clear them when content changes. UnfoldCMS fires outgoing, HMAC-signed webhooks on publish, update, and delete. Point one at a Rails endpoint:

# Verify the HMAC signature, then bust the cache
def cms_webhook
  head :forbidden and return unless valid_signature?(request)
  Rails.cache.delete_matched("blog/*")
  head :ok
end

An editor publishes, the CMS pings Rails, the stale cache clears — no waiting for a TTL. The HMAC signature means only your CMS can trigger the bust.

Rails CMS options compared

Option Language Editor for non-devs You maintain
Hand-built (ActiveAdmin) Ruby ⚠️ Data-shaped Everything
Comfy Mexican Sofa Ruby ✅ Decent The gem + your app
UnfoldCMS (headless) PHP (API) ✅ Full admin UI Just the fetch
Contentful SaaS ✅ Full admin UI The bill

A Rails-native CMS gem keeps everything in Ruby — good if you never want a second runtime. A headless CMS trades that for zero content-feature maintenance and a purpose-built editor.

Tradeoffs to weigh

  • A network dependency. Content comes from an API call. Caching hides the cost, but it's a moving part a local gem wouldn't add.
  • A second runtime to operate. UnfoldCMS is a PHP app you host. You don't write PHP, but you do run and update it. If your team won't operate anything but Ruby, that's a genuine objection.
  • No revision history. UnfoldCMS doesn't keep past versions of a post.
  • Preview needs building. Drafts 404 on the public API, so previewing unpublished content means a token-authed route you set up.

FAQ

Should I build a CMS in Rails or use a headless one? Build it in Rails if the content is simple and developer-edited. Use a headless CMS once you need a real editor for non-developers, plus media, scheduling, and SEO — features you'd otherwise reimplement and maintain yourself.

Can Rails consume a CMS written in another language? Yes. Headless CMSes expose an HTTP API. Rails calls it with Faraday or Net::HTTP and parses JSON — the CMS's language is irrelevant to your app.

How do I keep the Rails cache in sync with CMS edits? Register an outgoing webhook in the CMS that hits a Rails endpoint to clear the relevant cache keys on publish. Verify the HMAC signature so only your CMS can trigger it.

Does it support GraphQL? No — REST only. For Rails controllers, REST plus JSON parsing is simpler anyway.

Bottom line

Rolling your own CMS in Rails means maintaining features that aren't your product. A self-hosted headless CMS gives non-developers a real editor and hands Rails clean JSON over a cached API call. It's another runtime to operate, but you stop reimplementing publishing, media, and SEO by hand. For a team past the "blog is a scaffold" stage, that's the better trade.

See the API in the demo or read CMS vs custom build.

Related: CMS vs custom build · What is a content API · Headless vs traditional CMS

Free & Open Source

Own your CMS. No subscriptions.

Unfold CMS is free to download and self-host. Built on Laravel + React, full source code included.

Share this post:

Discussion

Comments (0)

Leave a Comment

Please log in to leave a comment.

Don't have an account? Register here

No comments yet. Be the first to share your thoughts!

Keep Reading

Related Posts

Back to all posts