macron-cms 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d33f2ffc21a60f2fed407e0b1aac793f203a304203a6d58c0a5c87680e7d33e3
4
- data.tar.gz: 27faeca2f7e1f4dc031e9786ec1739f19b59e2d088a0a7f7f5cdcc1f43bdb9b6
3
+ metadata.gz: 3507ec65e6552ca3c24c5084b6c4420aea93331ce3a3cfdd454d7e2020e5a9f2
4
+ data.tar.gz: d515fa7bd8c99e78dfcab2192d439fce806fa3d9c57c59440cf2968b7220b318
5
5
  SHA512:
6
- metadata.gz: 16aabb8fa8b2be75dc01a49f0c5e2267d85266a2c80566d6730095e8300df6cdb544962a1184a07fae8632145893f9a6307395762a1e16396b6fabcb402fef4b
7
- data.tar.gz: 8ce4de32d67626c86c5025bc78a07f1598a8cfc26d5ce3e980cf00581b8484b6976f0e9dfea91b8ea97f3df17c7542779c319151f186664256a9accdcc5c804d
6
+ metadata.gz: 6df0687512fdd1ddd220de626498a1763b52d438f0c6cbd8e066d96446829e5c8a18ec3a0bc2c7e42a192a260f24ed713a3d9139b2d5038bd5d3d12a02aa0303
7
+ data.tar.gz: a15f959a76152b8a83c3e4023c04bb5b8a4f37e3cb4b59f006374c7d46db0957e4186bcac9083469cb907ab7c501d1fb1a01abbde4f95b35ceebee06f052e6e8
data/README.md CHANGED
@@ -1,7 +1,13 @@
1
+ <p align="center">
2
+ <img src="docs/images/logo.jpg" alt="MacronCMS Logo" width="600" />
3
+ </p>
4
+
1
5
  # MacronCMS
2
6
 
3
- [![Gem Version](https://img.shields.io/badge/version-5.0.0-emerald.svg)](#version)
7
+ [![Gem Version](https://img.shields.io/badge/version-5.1.0-emerald.svg)](#version)
4
8
  [![Rails 8+](https://img.shields.io/badge/rails-8%2B-red.svg)](https://rubyonrails.org)
9
+ [![Live Demo](https://img.shields.io/badge/live_demo-blog.macron1.io-4F46E5.svg)](https://blog.macron1.io/)
10
+ [![Host Starter](https://img.shields.io/badge/host_starter-macron--cms--host-blue.svg)](https://github.com/macron1-automations/macron-cms-host)
5
11
  [![React](https://img.shields.io/badge/React-20232A?logo=react&logoColor=61DAFB)](https://react.dev)
6
12
  [![Three.js](https://img.shields.io/badge/Three.js-black?logo=three.js&logoColor=white)](https://threejs.org)
7
13
  [![MCP Server](https://img.shields.io/badge/MCP-Server-purple.svg)](https://github.com/macron1-automations/macron-cms-mcp)
@@ -9,6 +15,11 @@
9
15
 
10
16
  A simple, flexible CMS engine for Ruby on Rails, designed for building highly interactive content with dynamic content blocks, declarative schemas, and ViewComponent widgets.
11
17
 
18
+ > [!TIP]
19
+ > **Experience it live:** Visit **[blog.macron1.io](https://blog.macron1.io/)** to see a production publication built on MacronCMS featuring 3D Three.js widgets, dynamic KaTeX mathematical notation, and a zero-CLS magazine layout.
20
+ >
21
+ > Setting up a new host application? Use the [**MacronCMS Host Master Prompt**](https://github.com/macron1-automations/macron-cms-host) (`macron-cms-host`) with Google Antigravity, Claude Code, or Cursor to scaffold a complete, production-ready Rails 8.1+ host application in minutes.
22
+
12
23
  ---
13
24
 
14
25
  ## Overview
@@ -17,6 +28,25 @@ A simple, flexible CMS engine for Ruby on Rails, designed for building highly in
17
28
 
18
29
  ---
19
30
 
31
+ ## 🚀 Live Demo & Host Application Starter
32
+
33
+ ### 🌐 Live Production Demo: [blog.macron1.io](https://blog.macron1.io/)
34
+
35
+ See MacronCMS running in production at [**blog.macron1.io**](https://blog.macron1.io/):
36
+ - **Dynamic Content Blocks**: GitHub-Flavored Markdown, customizable headings, responsive images with Active Storage, blockquotes, and sandboxed embeds.
37
+ - **Interactive 3D WebGL**: Three.js quotes with CRT scanlines, 3D post-processed shader images, and holographic tilt cards.
38
+ - **Mathematical Typesetting**: CodeMirror-backed LaTeX equations with real-time KaTeX rendering.
39
+ - **Magazine Layout & Performance**: Zero-CLS editorial frontend with on-demand widget hydration, Russian-doll caching, and automated image variant warming.
40
+
41
+ ### ⚡ Build Your Host App with AI: [macron-cms-host](https://github.com/macron1-automations/macron-cms-host)
42
+
43
+ Rather than manually configuring content schemas, ViewComponent widgets, Hotwire streaming, and CDN settings from scratch, use the official **[MacronCMS Host Master Prompt](https://github.com/macron1-automations/macron-cms-host)** repository:
44
+ - **Turnkey AI Scaffolding**: Contains a self-contained master prompt ([`PROMPT.md`](https://github.com/macron1-automations/macron-cms-host/blob/main/PROMPT.md)) designed for agentic AI coding harnesses like **Google Antigravity**, **Claude Code**, and **Cursor**.
45
+ - **Interactive Interview**: The AI agent interviews you on your branding, layout preferences, widget tiers, and storage stack, then builds and verifies a tailored Rails 8.1+ host application.
46
+ - **Production-Ready Stack**: Configures PostgreSQL, Devise admin auth, Solid Cache/Queue, Active Storage with libvips WebP processing, Terser JS minification, and optional [`macron-cms-mcp`](https://github.com/macron1-automations/macron-cms-mcp) publishing integration.
47
+
48
+ ---
49
+
20
50
  ## Features
21
51
 
22
52
  ### 🛠️ Dedicated Admin Dashboard (`/cms`)
@@ -83,9 +113,10 @@ A simple, flexible CMS engine for Ruby on Rails, designed for building highly in
83
113
  - **Seamless Rendering Helpers**: Render all article content blocks ordered by `sort_order` with `<%= cms_render_article_contents(@article) %>`, or render individual blocks via `<%= cms_render_widget(article_content) %>`.
84
114
  - **Informative Error Handling**: Raises `Macron::Cms::MissingWidgetError` if a content type does not have a corresponding `Widgets::<Name>Component` in the host application.
85
115
 
86
- ### ⚡ High-Performance Preloading & O(1) Queries
116
+ ### ⚡ High-Performance Preloading, O(1) Queries & Russian-Doll Caching
87
117
  - **Zero N+1 Query Overhead**: Built-in `ArticleContent.for_display` scope combines Active Storage's `with_attached_files` with `.includes(:content)` to preload associations in constant-time batches.
88
118
  - **Bounded Query Execution**: Admin show views, high-frequency Turbo Stream inserts/reorders, and public host rendering (`cms_render_article_contents`) run in bounded O(1) database queries regardless of article length or attached media count.
119
+ - **Automatic Russian-Doll Cache Invalidation**: `ArticleContent` associations automatically touch the parent `Article` on all operations (block creation, edits, deletions, relative moves, and drag-and-drop batch reorders). Host applications can safely wrap article views in standard Rails fragment caching (`<% cache @article do %>`) with zero monkey-patching and guaranteed cache freshness.
89
120
 
90
121
  ### 🔒 Devise Authentication & Authorization
91
122
  - **Configurable Access Guard**: Protect the `/cms` engine namespace behind host application authentication.
@@ -122,6 +153,12 @@ A simple, flexible CMS engine for Ruby on Rails, designed for building highly in
122
153
 
123
154
  ## Installation
124
155
 
156
+ > [!TIP]
157
+ > **Starting a new project from scratch?**
158
+ > Instead of manually configuring models, widgets, and layout templates, use the [**MacronCMS Host Master Prompt**](https://github.com/macron1-automations/macron-cms-host) (`macron-cms-host`) to have your AI coding agent scaffold a complete, production-ready Rails 8.1+ host application with ViewComponent widgets, Devise authentication, and magazine layouts.
159
+ >
160
+ > To integrate MacronCMS into an existing Rails application, follow the manual installation steps below:
161
+
125
162
  Add this line to your application's `Gemfile`:
126
163
 
127
164
  ```ruby
@@ -537,7 +574,7 @@ end
537
574
 
538
575
  #### Host Application View (`app/views/articles/show.html.erb`)
539
576
 
540
- Use `cms_seo_meta` for SEO metadata and `cms_article_background_style` to apply custom background colors, images, and text colors directly to the layout:
577
+ Use `cms_seo_meta` for SEO metadata and `cms_article_background_style` to apply custom background colors, images, and text colors directly to the layout. Because all block operations automatically touch the parent article's timestamp, you can wrap article rendering in standard Rails fragment caching (`<% cache @article do %>`) for optimal performance:
541
578
 
542
579
  ```erb
543
580
  <% cms_seo_meta(@article) %>
@@ -545,18 +582,21 @@ Use `cms_seo_meta` for SEO metadata and `cms_article_background_style` to apply
545
582
  <% content_for :body_style, cms_article_background_style(@article) %>
546
583
  <% end %>
547
584
 
548
- <article class="max-w-4xl mx-auto px-4 py-12">
549
- <header class="pb-8 mb-8 border-b border-zinc-200">
550
- <h1 class="text-4xl font-bold" style="<%= "color: #{@article.text_color};" if @article.text_color.present? %>">
551
- <%= @article.title %>
552
- </h1>
553
- </header>
554
-
555
- <!-- Render all content blocks in order -->
556
- <div class="space-y-6">
557
- <%= cms_render_article_contents(@article) %>
558
- </div>
559
- </article>
585
+ <%# Automatically invalidated on block creation, edits, moves, reorders, or deletion %>
586
+ <% cache @article do %>
587
+ <article class="max-w-4xl mx-auto px-4 py-12">
588
+ <header class="pb-8 mb-8 border-b border-zinc-200">
589
+ <h1 class="text-4xl font-bold" style="<%= "color: #{@article.text_color};" if @article.text_color.present? %>">
590
+ <%= @article.title %>
591
+ </h1>
592
+ </header>
593
+
594
+ <!-- Render all content blocks in order -->
595
+ <div class="space-y-6">
596
+ <%= cms_render_article_contents(@article) %>
597
+ </div>
598
+ </article>
599
+ <% end %>
560
600
  ```
561
601
 
562
602
  In your application layout (`app/views/layouts/application.html.erb`), apply the `:body_style` slot and include the KaTeX and 3D widget assets:
@@ -3,6 +3,7 @@ module Macron
3
3
  class ArticleContentsController < ApplicationController
4
4
  before_action :set_article
5
5
  before_action :set_article_content, only: %i[update destroy move convert]
6
+ after_action :touch_article_on_reorder, only: [ :reorder, :move ]
6
7
 
7
8
  def create
8
9
  content = Content.find(params.dig(:article_content, :content_id))
@@ -250,6 +251,10 @@ module Macron
250
251
 
251
252
  render turbo_stream: turbo_stream_actions
252
253
  end
254
+
255
+ def touch_article_on_reorder
256
+ @article&.touch
257
+ end
253
258
  end
254
259
  end
255
260
  end
@@ -1,7 +1,7 @@
1
1
  module Macron
2
2
  module Cms
3
3
  class ArticleContent < ApplicationRecord
4
- belongs_to :article, class_name: "Macron::Cms::Article"
4
+ belongs_to :article, class_name: "Macron::Cms::Article", touch: true
5
5
  belongs_to :content, class_name: "Macron::Cms::Content"
6
6
 
7
7
  has_many_attached :files
@@ -1,5 +1,5 @@
1
1
  module Macron
2
2
  module Cms
3
- VERSION = "5.0.0"
3
+ VERSION = "5.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: macron-cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Medovyy