Project

open_blog

0.0
The project is in a healthy, maintained state
A Rails blog engine with reader pages, revision history, and agent publishing interfaces.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

Runtime

>= 2.8, < 3
>= 2.3, < 3
>= 1.6, < 2
>= 8.0, < 9.0
>= 4.7, < 6
 Project Readme

Open Blog

An agentic blog engine for Rails. Markdown and rich-text articles, responsive reader pages, immutable revision history, and publishing through Ruby, a JSON API, or MCP tools.

Gem version CI Installer Documentation License: MIT

Documentation · Installation · API reference · MCP · Changelog

Signal preset in light mode Signal preset in dark mode

Every publish, edit, approval, and removal leaves an immutable record. A reader can trust the dates and notices on the page, and an agent can publish without inventing a review.

Highlights

Reader pages Categories, tags, authors, series, search, Atom and JSON feeds, a sitemap, and structured data. The templates are copied into your app so you can change them.
Themes Three presets, Signal, Editorial, and Ink, each with light and dark mode. Change the palette from the configuration. Fonts ship with the gem; nothing loads from another site.
Publishing operations Ruby operations compute a revision identifier from the content, record each release, and refuse a public edit that does not say whether it is substantive, a correction, or maintenance.
JSON API and MCP Scoped tokens let editorial tools and AI agents publish through the same guarded path. Six agent workflows ship in the gem.
Approvals and provenance A post carries who wrote it, who reviewed which revision, and whether facts were checked. The AI notice on the page follows those records.
Adoption Import an existing blog with its known history, dates, and redirects, without claiming a new first publication.
Operations Policy pages, page views, diagnostics, and surface reports that check what readers actually see against the stored records.
AdminSuite Optional generated resources for a browser-based editor.

Requirements

Requirement Supported
Ruby 3.2, 3.3, 3.4, or 4.0
Rails 8.0 or 8.1
Database PostgreSQL or SQLite
Images Active Storage with libvips or ImageMagick

Every combination of Ruby, Rails, and database above runs in CI.

Install

bundle add open_blog
bin/rails generate open_blog:install

To run the latest unreleased source instead, use bundle add open_blog --github techwright-lab/open-blog.

Start bin/dev (or bin/rails server) and open /blog. The generator installs tables, mounts the engine at /blog, copies the reader views and browser controllers, writes config/initializers/open_blog.rb, and publishes a sample article. If it prints an API token, save it: the secret is shown once.

Set your site name, publisher, and public origin in the initializer, then run bin/rails open_blog:doctor to check the setup. The installation guide lists every generator option, and the configuration reference lists every setting with its default.

Publish a post

From Ruby:

result = OpenBlog::Publish.call(
  { title: "Garden notes", body: "Today in the garden.", provenance: "human_written" },
  actor: "Editor"
)
result.success?   # => true
result.post.path  # => "/blog/garden-notes"
result.records    # => { revision: "new", publication: "first", approval: nil }

From the JSON API, with a token from bin/rails open_blog:token:

curl -s -X POST https://example.com/blog/api/v1/posts \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"title":"Garden notes","body":"Today in the garden.","publish":true}'

From an agent, point an MCP client at https://example.com/blog/mcp with the same token. The blog_save_draft tool returns a preview link, and blog_publish_post records the release. Agents must show the exact text to a person and record only the approval they actually give; the publishing instructions spell this out.

A later edit of a public post must carry change: "substantive", "correction", or "maintenance". Without it the write is refused and nothing changes. Normal model saves and the operations keep this history; bulk SQL writes bypass it.

Guides

Guide Covers
Configuration Identity, routes, content gates, images, limits, and page views
Publishing Operations, previews, scheduling, approvals, and findings
JSON API and MCP Endpoints, tools, examples, and error codes
Reader pages and feeds Routes, search, feeds, dates, images, and policy pages
Adoption Import existing articles and preserve their known history
Customization Copied templates, stylesheets, and browser controllers
Themes Presets, palette overrides, design tokens, and fonts
AdminSuite, Diagnostics, Page views Optional editor, setup checks, surface reports, and analytics

Development

The gem tests run through a dummy host application. Set DB to sqlite or postgres:

bundle install
DB=sqlite RAILS_ENV=test bundle exec ruby bin/test
bundle exec rubocop

CI runs the matrix of Ruby 3.2 to 4.0, Rails 8.0 and 8.1, and both databases, plus browser tests and a fresh-application installer check with the built gem.

The documentation is Markdown in docs/, built with Jekyll and Just the Docs from a separate bundle. See working on the documentation for local preview and validation commands.

Releases

The Prepare Release workflow updates the version and changelog in a pull request. After review, merge, and successful checks, Publish publishes the verified package to RubyGems and creates or updates the GitHub Release. Merging ordinary changes does not publish a gem. See the release guide for the first-time Trusted Publishing setup.

License

Licensed under the MIT License.